erubis 2.0.1 → 2.1.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.
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