erubis 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. data/ChangeLog +150 -2
  2. data/LGPL +504 -0
  3. data/README.txt +14 -8
  4. data/benchmark/erubybench.rb +1 -1
  5. data/benchmark/erubybench.rhtml +3 -3
  6. data/bin/erubis +1 -1
  7. data/bin/notext +154 -0
  8. data/contrib/erubis +1036 -374
  9. data/contrib/inline-require +5 -3
  10. data/doc-api/classes/Erubis.html +43 -1
  11. data/doc-api/classes/Erubis/ArrayBufferEnhancer.html +14 -14
  12. data/doc-api/classes/Erubis/ArrayEnhancer.html +14 -14
  13. data/doc-api/classes/Erubis/Basic.html +112 -0
  14. data/doc-api/classes/Erubis/Basic/Converter.html +318 -0
  15. data/doc-api/classes/Erubis/Basic/Engine.html +130 -0
  16. data/doc-api/classes/Erubis/BiPatternEnhancer.html +14 -14
  17. data/doc-api/classes/Erubis/CGenerator.html +386 -0
  18. data/doc-api/classes/Erubis/Context.html +31 -32
  19. data/doc-api/classes/Erubis/Converter.html +231 -0
  20. data/doc-api/classes/Erubis/Ec.html +9 -283
  21. data/doc-api/classes/Erubis/Ejava.html +9 -274
  22. data/doc-api/classes/Erubis/Ejavascript.html +9 -298
  23. data/doc-api/classes/Erubis/Engine.html +68 -508
  24. data/doc-api/classes/Erubis/Eperl.html +9 -259
  25. data/doc-api/classes/Erubis/Ephp.html +9 -239
  26. data/doc-api/classes/Erubis/ErubisError.html +2 -2
  27. data/doc-api/classes/Erubis/Eruby.html +4 -187
  28. data/doc-api/classes/Erubis/EscapeEnhancer.html +9 -11
  29. data/doc-api/classes/Erubis/Escheme.html +9 -272
  30. data/doc-api/classes/Erubis/Evaluator.html +212 -0
  31. data/doc-api/classes/Erubis/Generator.html +410 -0
  32. data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +16 -16
  33. data/doc-api/classes/Erubis/Helper.html +112 -0
  34. data/doc-api/classes/Erubis/Helper/CachedRailsTemplate.html +198 -0
  35. data/doc-api/classes/Erubis/Helper/RailsTemplate.html +366 -0
  36. data/doc-api/classes/Erubis/JavaGenerator.html +359 -0
  37. data/doc-api/classes/Erubis/JavascriptGenerator.html +381 -0
  38. data/doc-api/classes/Erubis/Main.html +27 -25
  39. data/doc-api/classes/Erubis/NoCodeEnhancer.html +249 -0
  40. data/doc-api/classes/Erubis/NoCodeEruby.html +120 -0
  41. data/doc-api/classes/Erubis/NoTextEnhancer.html +8 -8
  42. data/doc-api/classes/Erubis/NotSupportedError.html +119 -0
  43. data/doc-api/classes/Erubis/OptimizedEruby.html +22 -304
  44. data/doc-api/classes/Erubis/OptimizedGenerator.html +439 -0
  45. data/doc-api/classes/Erubis/OptimizedXmlEruby.html +7 -7
  46. data/doc-api/classes/Erubis/PI.html +124 -0
  47. data/doc-api/classes/Erubis/PI/Converter.html +318 -0
  48. data/doc-api/classes/Erubis/PI/Ec.html +166 -0
  49. data/doc-api/classes/Erubis/PI/Ejava.html +166 -0
  50. data/doc-api/classes/Erubis/PI/Ejavascript.html +166 -0
  51. data/doc-api/classes/Erubis/PI/Engine.html +122 -0
  52. data/doc-api/classes/Erubis/PI/Eperl.html +166 -0
  53. data/doc-api/classes/Erubis/PI/Ephp.html +166 -0
  54. data/doc-api/classes/Erubis/PI/Eruby.html +155 -0
  55. data/doc-api/classes/Erubis/PI/Escheme.html +166 -0
  56. data/doc-api/classes/Erubis/PI/TinyEruby.html +305 -0
  57. data/doc-api/classes/Erubis/PercentLineEnhancer.html +7 -7
  58. data/doc-api/classes/Erubis/PerlGenerator.html +344 -0
  59. data/doc-api/classes/Erubis/PhpGenerator.html +350 -0
  60. data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +24 -24
  61. data/doc-api/classes/Erubis/PrintOutEnhancer.html +35 -35
  62. data/doc-api/classes/Erubis/RubyEvaluator.html +190 -0
  63. data/doc-api/classes/Erubis/RubyGenerator.html +327 -0
  64. data/doc-api/classes/Erubis/SchemeGenerator.html +382 -0
  65. data/doc-api/classes/Erubis/SimplifyEnhancer.html +17 -13
  66. data/doc-api/classes/Erubis/StdoutEnhancer.html +14 -14
  67. data/doc-api/classes/Erubis/StringBufferEnhancer.html +14 -14
  68. data/doc-api/classes/Erubis/TinyEruby.html +45 -40
  69. data/doc-api/classes/Erubis/XmlHelper.html +14 -14
  70. data/doc-api/created.rid +1 -1
  71. data/doc-api/files/__/README_txt.html +27 -9
  72. data/doc-api/files/erubis/context_rb.html +107 -0
  73. data/doc-api/files/erubis/converter_rb.html +114 -0
  74. data/doc-api/files/erubis/engine/ec_rb.html +2 -2
  75. data/doc-api/files/erubis/engine/ejava_rb.html +2 -2
  76. data/doc-api/files/erubis/engine/ejavascript_rb.html +2 -2
  77. data/doc-api/files/erubis/engine/enhanced_rb.html +2 -2
  78. data/doc-api/files/erubis/engine/eperl_rb.html +2 -2
  79. data/doc-api/files/erubis/engine/ephp_rb.html +2 -2
  80. data/doc-api/files/erubis/engine/eruby_rb.html +3 -2
  81. data/doc-api/files/erubis/engine/escheme_rb.html +2 -2
  82. data/doc-api/files/erubis/engine/optimized_rb.html +2 -2
  83. data/doc-api/files/erubis/engine_rb.html +6 -3
  84. data/doc-api/files/erubis/enhancer_rb.html +2 -9
  85. data/doc-api/files/erubis/error_rb.html +107 -0
  86. data/doc-api/files/erubis/evaluator_rb.html +115 -0
  87. data/doc-api/files/erubis/generator_rb.html +114 -0
  88. data/doc-api/files/erubis/helper/rails_rb.html +140 -0
  89. data/doc-api/files/erubis/helper_rb.html +1 -1
  90. data/doc-api/files/erubis/local-setting_rb.html +1 -1
  91. data/doc-api/files/erubis/main_rb.html +2 -2
  92. data/doc-api/files/erubis/tiny_rb.html +2 -2
  93. data/doc-api/files/erubis_rb.html +2 -2
  94. data/doc-api/fr_class_index.html +32 -0
  95. data/doc-api/fr_file_index.html +6 -0
  96. data/doc-api/fr_method_index.html +178 -136
  97. data/doc/users-guide.html +538 -199
  98. data/examples/{Makefile → basic/Makefile} +11 -11
  99. data/examples/basic/example.ec +42 -0
  100. data/examples/{example.ejava → basic/example.ejava} +5 -1
  101. data/examples/{example.ejavascript → basic/example.ejs} +0 -0
  102. data/examples/{example.eperl → basic/example.eperl} +2 -2
  103. data/examples/{example.ephp → basic/example.ephp} +0 -0
  104. data/examples/{example.eruby → basic/example.eruby} +0 -0
  105. data/examples/{example.escheme → basic/example.escheme} +0 -0
  106. data/examples/pi/Makefile +54 -0
  107. data/examples/pi/example.ec +42 -0
  108. data/examples/pi/example.ejava +45 -0
  109. data/examples/pi/example.ejs +16 -0
  110. data/examples/pi/example.eperl +16 -0
  111. data/examples/pi/example.ephp +17 -0
  112. data/examples/pi/example.eruby +15 -0
  113. data/examples/pi/example.escheme +26 -0
  114. data/lib/erubis.rb +15 -8
  115. data/lib/erubis/context.rb +54 -0
  116. data/lib/erubis/converter.rb +307 -0
  117. data/lib/erubis/engine.rb +57 -227
  118. data/lib/erubis/engine/ec.rb +31 -20
  119. data/lib/erubis/engine/ejava.rb +33 -21
  120. data/lib/erubis/engine/ejavascript.rb +30 -18
  121. data/lib/erubis/engine/enhanced.rb +7 -2
  122. data/lib/erubis/engine/eperl.rb +33 -19
  123. data/lib/erubis/engine/ephp.rb +32 -14
  124. data/lib/erubis/engine/eruby.rb +34 -7
  125. data/lib/erubis/engine/escheme.rb +34 -15
  126. data/lib/erubis/engine/optimized.rb +25 -11
  127. data/lib/erubis/enhancer.rb +53 -19
  128. data/lib/erubis/error.rb +24 -0
  129. data/lib/erubis/evaluator.rb +71 -0
  130. data/lib/erubis/generator.rb +83 -0
  131. data/lib/erubis/helper.rb +1 -1
  132. data/lib/erubis/helper/rails.rb +159 -0
  133. data/lib/erubis/local-setting.rb +1 -1
  134. data/lib/erubis/main.rb +87 -46
  135. data/lib/erubis/tiny.rb +81 -7
  136. data/test/assert-text-equal.rb +1 -1
  137. data/test/test-engines.rb +8 -9
  138. data/test/test-erubis.rb +196 -18
  139. data/test/{test-bin.rb → test-main.rb} +123 -21
  140. data/test/test-notext.rb +27 -0
  141. data/test/test.rb +5 -3
  142. data/test/testutil.rb +25 -36
  143. metadata +75 -13
  144. data/COPYING +0 -340
  145. data/examples/example.ec +0 -24
@@ -0,0 +1,307 @@
1
+ ##
2
+ ## $Rev: 37 $
3
+ ## $Release: 2.1.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+ require 'abstract'
8
+
9
+ module Erubis
10
+
11
+
12
+ ##
13
+ ## convert
14
+ ##
15
+ module Converter
16
+
17
+ attr_accessor :preamble, :postamble, :escape
18
+
19
+ def self.supported_properties # :nodoc:
20
+ return [
21
+ [:preamble, nil, "preamble (no preamble when false)"],
22
+ [:postamble, nil, "postamble (no postamble when false)"],
23
+ [:escape, nil, "escape expression or not in default"],
24
+ ]
25
+ end
26
+
27
+ def init_converter(properties={})
28
+ @preamble = properties[:preamble]
29
+ @postamble = properties[:postamble]
30
+ @escape = properties[:escape]
31
+ end
32
+
33
+ ## convert input string into target language
34
+ def convert(input)
35
+ codebuf = "" # or []
36
+ @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
37
+ convert_input(codebuf, input)
38
+ @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
39
+ return codebuf # or codebuf.join()
40
+ end
41
+
42
+ protected
43
+
44
+ ##
45
+ ## (abstract) convert input to code
46
+ ##
47
+ def convert_input(codebuf, input)
48
+ not_implemented
49
+ end
50
+
51
+ end
52
+
53
+
54
+ module Basic
55
+ end
56
+
57
+
58
+ ##
59
+ ## basic converter which supports '<% ... %>' notation.
60
+ ##
61
+ module Basic::Converter
62
+ include Erubis::Converter
63
+
64
+ def self.supported_properties # :nodoc:
65
+ return [
66
+ [:pattern, '<% %>', "embed pattern"],
67
+ [:trim, true, "trim spaces around <% ... %>"],
68
+ ]
69
+ end
70
+
71
+ attr_accessor :pattern, :trim
72
+
73
+ def init_converter(properties={})
74
+ super(properties)
75
+ @pattern = properties[:pattern]
76
+ @trim = properties[:trim] != false
77
+ end
78
+
79
+ #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
80
+ DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
81
+
82
+ ## return regexp of pattern to parse eRuby script
83
+ def pattern_regexp(pattern=@pattern)
84
+ if pattern.nil? || pattern == '<% %>'
85
+ return DEFAULT_REGEXP
86
+ else
87
+ prefix, postfix = pattern.split()
88
+ #return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
89
+ return /(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
90
+ end
91
+ end
92
+ protected :pattern_regexp
93
+
94
+ def convert_input(src, input)
95
+ regexp = pattern_regexp(@pattern)
96
+ pos = 0
97
+ input.scan(regexp) do |lspace, indicator, code, rspace|
98
+ match = Regexp.last_match()
99
+ index = match.begin(0)
100
+ text = input[pos, index - pos]
101
+ pos = match.end(0)
102
+ add_text(src, text)
103
+ ## * when '<%= %>', do nothing
104
+ ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
105
+ if !indicator # <% %>
106
+ if @trim && lspace && rspace
107
+ add_stmt(src, "#{lspace}#{code}#{rspace}")
108
+ else
109
+ add_text(src, lspace) if lspace
110
+ add_stmt(src, code)
111
+ add_text(src, rspace) if rspace
112
+ end
113
+ elsif indicator[0] == ?\# # <%# %>
114
+ n = code.count("\n") + (rspace ? 1 : 0)
115
+ if @trim && lspace && rspace
116
+ add_stmt(src, "\n" * n)
117
+ else
118
+ add_text(src, lspace) if lspace
119
+ add_stmt(src, "\n" * n)
120
+ add_text(src, rspace) if rspace
121
+ end
122
+ else # <%= %>
123
+ add_text(src, lspace) if lspace
124
+ add_expr(src, code, indicator)
125
+ add_text(src, rspace) if rspace
126
+ end
127
+ end
128
+ rest = $' || input # add input when no matched
129
+ add_text(src, rest)
130
+ end
131
+
132
+ ## add expression code to src
133
+ def add_expr(src, code, indicator)
134
+ case indicator
135
+ when '='
136
+ @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
137
+ when '=='
138
+ @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
139
+ when '==='
140
+ add_expr_debug(src, code)
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+
147
+ module PI
148
+ end
149
+
150
+ ##
151
+ ## Processing Instructions (PI) converter for XML.
152
+ ## this class converts '<?rb ... ?>' and '${...}' notation.
153
+ ##
154
+ module PI::Converter
155
+ include Erubis::Converter
156
+
157
+ def self.desc # :nodoc:
158
+ "use processing instructions (PI) instead of '<% %>'"
159
+ end
160
+
161
+ def self.supported_properties # :nodoc:
162
+ return [
163
+ [:trim, true, "trim spaces around <% ... %>"],
164
+ [:pi, 'rb', "PI (Processing Instrunctions) name"],
165
+ [:embchar, '@', "char for embedded expression pattern('@{...}@')"],
166
+ [:pattern, '<% %>', "embed pattern"],
167
+ ]
168
+ end
169
+
170
+ attr_accessor :pi, :prefix
171
+
172
+ def init_converter(properties={})
173
+ super(properties)
174
+ @trim = !(properties[:trim] == false)
175
+ @pi = properties[:pi] if properties[:pi]
176
+ @embchar = properties[:embchar] || '@'
177
+ @pattern = properties[:pattern]
178
+ @pattern = '<% %>' if @pattern.nil? #|| @pattern == true
179
+ end
180
+
181
+ def convert(input)
182
+ code = super(input)
183
+ return @header || @footer ? "#{@header}#{code}#{@footer}" : code
184
+ end
185
+
186
+ protected
187
+
188
+ def convert_input(codebuf, input)
189
+ parse_stmts(codebuf, input)
190
+ #parse_stmts2(codebuf, input)
191
+ end
192
+
193
+ def parse_stmts(codebuf, input)
194
+ #regexp = pattern_regexp(@pattern)
195
+ @pi ||= 'e'
196
+ @stmt_pattern ||= /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
197
+ pos = 0
198
+ input.scan(@stmt_pattern) do |lspace, pi_arg, code, rspace|
199
+ match = Regexp.last_match
200
+ index = match.begin(0)
201
+ text = input[pos, index - pos]
202
+ pos = match.end(0)
203
+ parse_exprs(codebuf, text) # unless text.empty?
204
+ if @trim && lspace && rspace
205
+ add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
206
+ else
207
+ add_text(codebuf, lspace)
208
+ add_pi_stmt(codebuf, code, pi_arg)
209
+ add_text(codebuf, rspace)
210
+ end
211
+ end
212
+ rest = $' || input
213
+ parse_exprs(codebuf, rest)
214
+ end
215
+
216
+ def parse_exprs(codebuf, input)
217
+ unless @expr_pattern
218
+ ch = Regexp.escape(@embchar)
219
+ if @pattern
220
+ left, right = @pattern.split(' ')
221
+ @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
222
+ else
223
+ @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
224
+ end
225
+ end
226
+ pos = 0
227
+ input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
228
+ indicator = indicator1 || indicator2
229
+ code = code1 || code2
230
+ match = Regexp.last_match
231
+ index = match.begin(0)
232
+ text = input[pos, index - pos]
233
+ pos = match.end(0)
234
+ add_text(codebuf, text) # unless text.empty?
235
+ add_pi_expr(codebuf, code, indicator)
236
+ end
237
+ rest = $' || input
238
+ add_text(codebuf, rest)
239
+ end
240
+
241
+ def add_pi_stmt(codebuf, code, pi_arg) # :nodoc:
242
+ case pi_arg
243
+ when 'header' ; @header = code
244
+ when 'footer' ; @footer = code
245
+ when 'comment'; add_stmt(codebuf, "\n" * code.count("\n"))
246
+ when 'value' ; add_expr_literal(codebuf, code)
247
+ else ; add_stmt(codebuf, code)
248
+ end
249
+ end
250
+
251
+ def add_pi_expr(codebuf, code, indicator) # :nodoc:
252
+ case indicator
253
+ when nil, '', '==' # @{...}@ or <%== ... %>
254
+ @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
255
+ when '!', '=' # @!{...}@ or <%= ... %>
256
+ @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
257
+ when '!!', '===' # @!!{...}@ or <%=== ... %>
258
+ add_expr_debug(codebuf, code)
259
+ else
260
+ # ignore
261
+ end
262
+ end
263
+
264
+ ## (obsolete) equivarent to parse_stmts(), but a little slower than it.
265
+ def parse_stmts2(codebuf, input) # :nodoc:
266
+ #regexp = pattern_regexp(@pattern)
267
+ @pi ||= 'e'
268
+ unless @embedded_pattern
269
+ ch = Regexp.escape(@embchar)
270
+ if @pattern
271
+ left, right = @pattern.split(' ')
272
+ @embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
273
+ else
274
+ @embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
275
+ end
276
+ end
277
+ pos = 0
278
+ input.scan(@embedded_pattern) do |lspace, pi_arg, stmt, rspace,
279
+ indicator1, expr1, indicator2, expr2|
280
+ match = Regexp.last_match
281
+ index = match.begin(0)
282
+ text = input[pos, index - pos]
283
+ pos = match.end(0)
284
+ add_text(codebuf, text) # unless text.empty?
285
+ if stmt
286
+ code = stmt
287
+ if @trim && lspace && rspace
288
+ add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
289
+ else
290
+ add_text(codebuf, lspace)
291
+ add_pi_stmt(codebuf, code, pi_arg)
292
+ add_text(codebuf, rspace)
293
+ end
294
+ else
295
+ code = expr1 || expr2
296
+ indicator = indicator1 || indicator2
297
+ add_pi_expr(codebuf, code, indicator)
298
+ end
299
+ end
300
+ rest = $' || input
301
+ add_text(codebuf, rest)
302
+ end
303
+
304
+ end
305
+
306
+
307
+ end
@@ -1,93 +1,40 @@
1
1
  ##
2
- ## $Rev: 24 $
3
- ## $Release: 2.0.1 $
2
+ ## $Rev: 32 $
3
+ ## $Release: 2.1.0 $
4
4
  ## copyright(c) 2006 kuwata-lab all rights reserved.
5
5
  ##
6
6
 
7
- require 'abstract'
8
7
 
8
+ require 'erubis/generator'
9
+ require 'erubis/converter'
10
+ require 'erubis/evaluator'
11
+ require 'erubis/context'
9
12
 
10
- module Erubis
11
-
12
-
13
- ##
14
- ## base error class
15
- ##
16
- class ErubisError < StandardError
17
- end
18
-
19
-
20
- ##
21
- ## .[abstract] context object for Engine#evaluate
22
- ##
23
- ## ex.
24
- ## template = <<'END'
25
- ## Hello <%= @user %>!
26
- ## <% for item in @list %>
27
- ## - <%= item %>
28
- ## <% end %>
29
- ## END
30
- ##
31
- ## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
32
- ## # or
33
- ## # context = Erubis::Context.new
34
- ## # context[:user] = 'World'
35
- ## # context[:list] = ['a', 'b', 'c']
36
- ##
37
- ## eruby = Erubis::Eruby.new(template)
38
- ## print eruby.evaluate(context)
39
- ##
40
- class Context
41
-
42
- def initialize(hash=nil)
43
- hash.each do |name, value|
44
- self[name] = value
45
- end if hash
46
- end
47
13
 
48
- def [](key)
49
- return instance_variable_get("@#{key}")
50
- end
51
-
52
- def []=(key, value)
53
- return instance_variable_set("@#{key}", value)
54
- end
55
-
56
- def keys
57
- return instance_variables.collect { |name| name[1,name.length-1] }
58
- end
59
-
60
- end
14
+ module Erubis
61
15
 
62
16
 
63
17
  ##
64
- ## .[abstract] base engine class
18
+ ## (abstract) abstract engine class.
19
+ ## subclass must include evaluator and converter module.
65
20
  ##
66
21
  class Engine
22
+ #include Evaluator
23
+ #include Converter
24
+ #include Generator
67
25
 
68
- def self.supported_properties # :nodoc:
69
- return [
70
- [:pattern, '<% %>', "embed pattern"],
71
- #[:filename, nil, "filename"],
72
- [:trim, true, "trim spaces around <% ... %>"],
73
- [:preamble, nil, "preamble (no preamble when false)"],
74
- [:postamble, nil, "postamble (no postamble when false)"],
75
- [:escape, nil, "escape function name"],
76
- ]
26
+ # convert input string and set it to @src
27
+ def convert!(input)
28
+ @src = convert(input)
77
29
  end
78
30
 
79
- def initialize(input, properties={})
80
- #@input = input
81
- @pattern = properties[:pattern]
82
- @filename = properties[:filename]
83
- @trim = properties[:trim] != false
84
- @preamble = properties[:preamble]
85
- @postamble = properties[:postamble]
86
- @escape = properties[:escape]
87
- @src = compile(input) if input
31
+ def initialize(input=nil, properties={})
32
+ #@input = input
33
+ init_generator(properties)
34
+ init_converter(properties)
35
+ init_evaluator(properties)
36
+ @src = convert(input) if input
88
37
  end
89
- attr_reader :src
90
- attr_accessor :filename
91
38
 
92
39
  ## load file and create engine object
93
40
  def self.load_file(filename, properties={})
@@ -98,174 +45,57 @@ module Erubis
98
45
  return engine
99
46
  end
100
47
 
101
- ## eval(@src) with binding object
102
- def result(_binding_or_hash=TOPLEVEL_BINDING)
103
- _arg = _binding_or_hash
104
- if _arg.is_a?(Hash)
105
- ## load _context data as local variables by eval
106
- eval _arg.keys.inject("") { |s, k| s << "#{k.to_s} = _arg[#{k.inspect}];" }
107
- _arg = binding()
108
- end
109
- return eval(@src, _arg, (@filename || '(erubis)'))
110
- end
111
48
 
112
- ## invoke context.instance_eval(@src)
113
- def evaluate(context=Context.new)
114
- context = Context.new(context) if context.is_a?(Hash)
115
- return context.instance_eval(@src, (@filename || '(erubis)'))
116
- end
117
-
118
- DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
119
-
120
- ## return regexp of pattern to parse eRuby script
121
- def pattern_regexp(pattern=@pattern)
122
- if pattern.nil? || pattern == '<% %>'
123
- return DEFAULT_REGEXP
49
+ ##
50
+ ## helper method to convert and evaluate input text with context object.
51
+ ## context may be Binding, Hash, or Object.
52
+ ##
53
+ def process(input, context=nil, filename=nil)
54
+ code = convert(input)
55
+ filename ||= '(erubis)'
56
+ if context.is_a?(Binding)
57
+ return eval(code, context, filename)
124
58
  else
125
- prefix, postfix = pattern.split()
126
- return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
59
+ context = Context.new(context) if context.is_a?(Hash)
60
+ return context.instance_eval(code, filename)
127
61
  end
128
62
  end
129
- protected :pattern_regexp
130
63
 
131
- ## compile input string into target language
132
- def compile(input)
133
- src = ""
134
- @preamble.nil? ? add_preamble(src) : (@preamble && (src << @preamble))
135
- regexp = pattern_regexp(@pattern)
136
- input.scan(regexp) do |text, lspace, indicator, code, rspace|
137
- add_text(src, text)
138
- ## * when '<%= %>', do nothing
139
- ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
140
- if !indicator # <% %>
141
- if @trim && lspace && rspace
142
- add_stmt(src, "#{lspace}#{code}#{rspace}")
143
- else
144
- add_text(src, lspace) if lspace
145
- add_stmt(src, code)
146
- add_text(src, rspace) if rspace
147
- end
148
- elsif indicator[0] == ?\# # <%# %>
149
- n = code.count("\n") + (rspace ? 1 : 0)
150
- if @trim && lspace && rspace
151
- add_stmt(src, "\n" * n)
152
- else
153
- add_text(src, lspace) if lspace
154
- add_stmt(src, "\n" * n)
155
- add_text(src, rspace) if rspace
156
- end
157
- #flag_trim = @trim && lspace && rspace
158
- #add_text(src, lspace) if !flag_trim && lspace
159
- #n = code.count("\n") + (rspace ? 1 : 0)
160
- #add_stmt(src, "\n" * n)
161
- #add_text(src, rspace) if !flag_trim && rspace
162
- else # <%= %>
163
- add_text(src, lspace) if lspace
164
- add_expr(src, code, indicator)
165
- add_text(src, rspace) if rspace
166
- end
167
- #if indicator && indicator[0] == ?=
168
- # flag_trim = false
169
- #else
170
- # flag_trim = @trim && lspace && rspace
171
- #end
172
- ##flag_trim = @trim && !(indicator && indicator[0]==?=) && lspace && rspace
173
- #add_text(src, text)
174
- #add_text(src, lspace) if !flag_trim && lspace
175
- #if !indicator # <% %>
176
- # code = "#{lspace}#{code}#{rspace}" if flag_trim
177
- # add_stmt(src, code)
178
- #elsif indicator[0] == ?\# # <%# %>
179
- # n = code.count("\n") + (rspace ? 1 : 0)
180
- # add_stmt(src, "\n" * n)
181
- #else # <%= %>
182
- # add_expr(src, code, indicator)
183
- #end
184
- #add_text(src, rspace) if !flag_trim && rspace
185
- end
186
- rest = $' || input # add input when no matched
187
- add_text(src, rest)
188
- @postamble.nil? ? add_postamble(src) : (@postamble && (src << @postamble))
189
- return src
190
- end
191
64
 
192
- ## compile input string and set it to @src
193
- def compile!(input)
194
- @src = compile(input)
195
- end
196
-
197
- protected
198
-
199
- ## .[abstract] escape text string
200
65
  ##
201
- ## ex.
202
- ## def escape_text(text)
203
- ## return text.dump
204
- ## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
205
- ## end
206
- def escape_text(text)
207
- not_implemented
208
- end
209
-
210
- ## .[abstract] return escaped expression code
66
+ ## helper method evaluate Proc object iwth contect object.
67
+ ## context may be Binding, Hash, or Object.
211
68
  ##
212
- ## ex.
213
- ## def escaped_expr(code)
214
- ## @escape ||= 'escape'
215
- ## return "#{@escape}(#{code.strip})"
216
- ## end
217
- def escaped_expr(code)
218
- not_implemented
219
- end
220
-
221
- ## .[abstract] add @preamble to src
222
- def add_preamble(src)
223
- not_implemented
224
- end
225
-
226
- ## .[abstract] add text string to src
227
- def add_text(src, text)
228
- not_implemented
229
- end
230
-
231
- ## .[abstract] add statement code to src
232
- def add_stmt(src, code)
233
- not_implemented
234
- end
235
-
236
- ## add expression code to src
237
- def add_expr(src, code, indicator)
238
- case indicator
239
- when '='
240
- add_expr_literal(src, code)
241
- when '=='
242
- add_expr_escaped(src, code)
243
- when '==='
244
- add_expr_debug(src, code)
69
+ def process_proc(proc_obj, context=nil, filename=nil)
70
+ if context.is_a?(Binding)
71
+ filename ||= '(erubis)'
72
+ return eval(proc_obj, context, filename)
73
+ else
74
+ context = Context.new(context) if context.is_a?(Hash)
75
+ return context.instance_eval(&proc_obj)
245
76
  end
246
77
  end
247
78
 
248
- ## .[abstract] add expression literal code to src. this is called by add_expr().
249
- def add_expr_literal(src, code)
250
- not_implemented
251
- end
252
79
 
253
- ## .[abstract] add escaped expression code to src. this is called by add_expr().
254
- def add_expr_escaped(src, code)
255
- not_implemented
256
- end
80
+ end # end of class Engine
257
81
 
258
- ## .[abstract] add expression code to src for debug. this is called by add_expr().
259
- def add_expr_debug(src, code)
260
- not_implemented
261
- end
262
82
 
263
- ## .[abstract] add @postamble to src
264
- def add_postamble(src)
265
- not_implemented
266
- end
83
+ ##
84
+ ## (abstract) base engine class for Eruby, Eperl, Ejava, and so on.
85
+ ## subclass must include generator.
86
+ ##
87
+ class Basic::Engine < Engine
88
+ include Evaluator
89
+ include Basic::Converter
90
+ include Generator
91
+ end
267
92
 
268
- end # end of class Engine
93
+
94
+ class PI::Engine < Engine
95
+ include Evaluator
96
+ include PI::Converter
97
+ include Generator
98
+ end
269
99
 
270
100
 
271
101
  end