erubis 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/ChangeLog +45 -18
  2. data/README.txt +80 -0
  3. data/benchmark/erubybench-lib.rb +189 -0
  4. data/benchmark/erubybench.rb +364 -0
  5. data/benchmark/erubybench.rhtml +61 -0
  6. data/benchmark/erubybench.yaml +61 -0
  7. data/bin/erubis +4 -180
  8. data/contrib/erubis +2297 -0
  9. data/contrib/inline-require +151 -0
  10. data/doc-api/classes/Erubis.html +236 -0
  11. data/doc-api/classes/Erubis/ArrayBufferEnhancer.html +175 -0
  12. data/doc-api/classes/Erubis/ArrayBufferEruby.html +120 -0
  13. data/doc-api/classes/Erubis/ArrayEnhancer.html +174 -0
  14. data/doc-api/classes/Erubis/ArrayEruby.html +120 -0
  15. data/doc-api/classes/Erubis/BiPatternEnhancer.html +212 -0
  16. data/doc-api/classes/Erubis/BiPatternEruby.html +120 -0
  17. data/doc-api/classes/Erubis/CommandOptionError.html +113 -0
  18. data/doc-api/classes/Erubis/Context.html +249 -0
  19. data/doc-api/classes/Erubis/Ec.html +399 -0
  20. data/doc-api/classes/Erubis/Ejava.html +366 -0
  21. data/doc-api/classes/Erubis/Ejavascript.html +390 -0
  22. data/doc-api/classes/Erubis/Engine.html +711 -0
  23. data/doc-api/classes/Erubis/Eperl.html +350 -0
  24. data/doc-api/classes/Erubis/Ephp.html +308 -0
  25. data/doc-api/classes/Erubis/ErubisError.html +117 -0
  26. data/doc-api/classes/Erubis/Eruby.html +310 -0
  27. data/doc-api/classes/Erubis/EscapeEnhancer.html +167 -0
  28. data/doc-api/classes/Erubis/EscapedEc.html +120 -0
  29. data/doc-api/classes/Erubis/EscapedEjava.html +120 -0
  30. data/doc-api/classes/Erubis/EscapedEjavascript.html +120 -0
  31. data/doc-api/classes/Erubis/EscapedEperl.html +120 -0
  32. data/doc-api/classes/Erubis/EscapedEphp.html +120 -0
  33. data/doc-api/classes/Erubis/EscapedEruby.html +127 -0
  34. data/doc-api/classes/Erubis/EscapedEscheme.html +120 -0
  35. data/doc-api/classes/Erubis/Escheme.html +389 -0
  36. data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +264 -0
  37. data/doc-api/classes/Erubis/HeaderFooterEruby.html +120 -0
  38. data/doc-api/classes/Erubis/Main.html +318 -0
  39. data/doc-api/classes/Erubis/NoTextEnhancer.html +159 -0
  40. data/doc-api/classes/Erubis/NoTextEruby.html +120 -0
  41. data/doc-api/classes/Erubis/OptimizedEruby.html +445 -0
  42. data/doc-api/classes/Erubis/OptimizedXmlEruby.html +163 -0
  43. data/doc-api/classes/Erubis/PercentLineEnhancer.html +174 -0
  44. data/doc-api/classes/Erubis/PercentLineEruby.html +120 -0
  45. data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +212 -0
  46. data/doc-api/classes/Erubis/PrintEnabledEruby.html +120 -0
  47. data/doc-api/classes/Erubis/PrintOutEnhancer.html +244 -0
  48. data/doc-api/classes/Erubis/PrintOutEruby.html +120 -0
  49. data/doc-api/classes/Erubis/PrintOutSimplifiedEruby.html +121 -0
  50. data/doc-api/classes/Erubis/SimplifiedEruby.html +120 -0
  51. data/doc-api/classes/Erubis/SimplifyEnhancer.html +185 -0
  52. data/doc-api/classes/Erubis/StdoutEnhancer.html +173 -0
  53. data/doc-api/classes/Erubis/StdoutEruby.html +120 -0
  54. data/doc-api/classes/Erubis/StdoutSimplifiedEruby.html +121 -0
  55. data/doc-api/classes/Erubis/StringBufferEnhancer.html +174 -0
  56. data/doc-api/classes/Erubis/StringBufferEruby.html +120 -0
  57. data/doc-api/classes/Erubis/StringIOEruby.html +120 -0
  58. data/doc-api/classes/Erubis/TinyEruby.html +305 -0
  59. data/doc-api/classes/Erubis/XmlEruby.html +130 -0
  60. data/doc-api/classes/Erubis/XmlHelper.html +193 -0
  61. data/doc-api/created.rid +1 -0
  62. data/doc-api/files/__/README_txt.html +214 -0
  63. data/doc-api/files/erubis/engine/ec_rb.html +115 -0
  64. data/doc-api/files/erubis/engine/ejava_rb.html +115 -0
  65. data/doc-api/files/erubis/engine/ejavascript_rb.html +115 -0
  66. data/doc-api/files/erubis/engine/enhanced_rb.html +115 -0
  67. data/doc-api/files/erubis/engine/eperl_rb.html +115 -0
  68. data/doc-api/files/erubis/engine/ephp_rb.html +115 -0
  69. data/doc-api/files/erubis/engine/eruby_rb.html +115 -0
  70. data/doc-api/files/erubis/engine/escheme_rb.html +115 -0
  71. data/doc-api/files/erubis/engine/optimized_rb.html +114 -0
  72. data/doc-api/files/erubis/engine_rb.html +114 -0
  73. data/doc-api/files/erubis/enhancer_rb.html +114 -0
  74. data/doc-api/files/erubis/helper_rb.html +107 -0
  75. data/doc-api/files/erubis/local-setting_rb.html +107 -0
  76. data/doc-api/files/erubis/main_rb.html +125 -0
  77. data/doc-api/files/erubis/tiny_rb.html +107 -0
  78. data/doc-api/files/erubis_rb.html +118 -0
  79. data/doc-api/fr_class_index.html +77 -0
  80. data/doc-api/fr_file_index.html +43 -0
  81. data/doc-api/fr_method_index.html +157 -0
  82. data/doc-api/index.html +24 -0
  83. data/doc-api/rdoc-style.css +208 -0
  84. data/doc/users-guide.html +1507 -375
  85. data/examples/Makefile +53 -0
  86. data/examples/example.ec +24 -0
  87. data/examples/example.ejava +41 -0
  88. data/examples/example.ejavascript +16 -0
  89. data/examples/example.eperl +16 -0
  90. data/examples/example.ephp +17 -0
  91. data/examples/example.eruby +15 -0
  92. data/examples/example.escheme +26 -0
  93. data/lib/erubis.rb +37 -269
  94. data/lib/erubis/engine.rb +260 -0
  95. data/lib/erubis/engine/ec.rb +106 -0
  96. data/lib/erubis/engine/ejava.rb +101 -0
  97. data/lib/erubis/engine/ejavascript.rb +104 -0
  98. data/lib/erubis/engine/enhanced.rb +102 -0
  99. data/lib/erubis/engine/eperl.rb +83 -0
  100. data/lib/erubis/engine/ephp.rb +84 -0
  101. data/lib/erubis/engine/eruby.rb +91 -0
  102. data/lib/erubis/engine/escheme.rb +96 -0
  103. data/lib/erubis/engine/optimized.rb +114 -0
  104. data/lib/erubis/enhancer.rb +487 -0
  105. data/lib/erubis/helper.rb +53 -0
  106. data/lib/erubis/local-setting.rb +10 -0
  107. data/lib/erubis/main.rb +368 -0
  108. data/lib/erubis/tiny.rb +65 -0
  109. data/test/assert-text-equal.rb +45 -0
  110. data/test/test-bin.rb +222 -45
  111. data/test/test-engines.rb +343 -0
  112. data/test/test-erubis.rb +836 -501
  113. data/test/test.rb +27 -0
  114. data/test/testutil.rb +86 -0
  115. metadata +131 -8
  116. data/README +0 -50
@@ -0,0 +1,53 @@
1
+ ##
2
+ ## $Rev: 21 $
3
+ ## $Release: 2.0.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+
8
+ module Erubis
9
+
10
+ ##
11
+ ## helper for xml
12
+ ##
13
+ module XmlHelper
14
+
15
+ module_function
16
+
17
+ ESCAPE_TABLE = {
18
+ '&' => '&',
19
+ '<' => '&lt;',
20
+ '>' => '&gt;',
21
+ '"' => '&quot;',
22
+ "'" => '&#039;',
23
+ }
24
+
25
+ def escape_xml(obj)
26
+ #table = ESCAPE_TABLE
27
+ #obj.to_s.gsub(/[&<>"]/) { |s| table[s] } # or /[&<>"']/
28
+ obj.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/
29
+ #obj.to_s.gsub(SCAN_REGEXP) { |s| ESCAPE_TABLE[s] }
30
+ #obj.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
31
+ end
32
+
33
+ #--
34
+ #def escape_xml(obj)
35
+ # str = obj.to_s.dup
36
+ # #str = obj.to_s
37
+ # #str = str.dup if obj.__id__ == str.__id__
38
+ # str.gsub!(/&/, '&amp;')
39
+ # str.gsub!(/</, '&lt;')
40
+ # str.gsub!(/>/, '&gt;')
41
+ # str.gsub!(/"/, '&quot;')
42
+ # str.gsub!(/'/, '&#039;')
43
+ # return str
44
+ #end
45
+ #++
46
+
47
+ alias h escape_xml
48
+ alias html_escape escape_xml
49
+
50
+ end
51
+
52
+
53
+ end
@@ -0,0 +1,10 @@
1
+ ##
2
+ ## $Rev: 13 $
3
+ ## $Release: 2.0.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+ ##
8
+ ## you can add site-local settings here.
9
+ ## this files is 'require'd by erubis.rb
10
+ ##
@@ -0,0 +1,368 @@
1
+ ###
2
+ ### $Rev: 21 $
3
+ ### $Release: 2.0.0 $
4
+ ### copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ require 'yaml'
8
+ require 'erubis'
9
+ require 'erubis/tiny'
10
+ require 'erubis/engine/enhanced'
11
+ require 'erubis/engine/optimized'
12
+ require 'erubis/engine/eruby'
13
+ require 'erubis/engine/ephp'
14
+ require 'erubis/engine/ec'
15
+ require 'erubis/engine/ejava'
16
+ require 'erubis/engine/escheme'
17
+ require 'erubis/engine/eperl'
18
+ require 'erubis/engine/ejavascript'
19
+
20
+
21
+ module Erubis
22
+
23
+
24
+ Ejs = Ejavascript
25
+ EscapedEjs = EscapedEjavascript
26
+
27
+
28
+ class CommandOptionError < ErubisError
29
+ end
30
+
31
+
32
+ ##
33
+ ## main class of command
34
+ ##
35
+ ## ex.
36
+ ## Main.main(ARGV)
37
+ ##
38
+ class Main
39
+
40
+ def self.main(argv=ARGV)
41
+ status = 0
42
+ begin
43
+ Main.new.execute(ARGV)
44
+ rescue CommandOptionError => ex
45
+ $stderr.puts ex.message
46
+ status = 1
47
+ end
48
+ exit(status)
49
+ end
50
+
51
+ def initialize
52
+ @single_options = "hvxTtSbeB"
53
+ @arg_options = "pcrfKIlaE"
54
+ @option_names = {
55
+ ?h => :help,
56
+ ?v => :version,
57
+ ?x => :source,
58
+ ?T => :notrim,
59
+ ?t => :untabify,
60
+ ?S => :intern,
61
+ ?b => :bodyonly,
62
+ ?B => :binding,
63
+ ?p => :pattern,
64
+ ?c => :class,
65
+ ?e => :escape,
66
+ ?r => :requires,
67
+ ?f => :yamlfiles,
68
+ ?K => :kanji,
69
+ ?I => :includes,
70
+ ?l => :lang,
71
+ ?a => :action,
72
+ ?E => :enhancers,
73
+ }
74
+ assert unless @single_options.length + @arg_options.length == @option_names.length
75
+ (@single_options + @arg_options).each_byte do |ch|
76
+ assert unless @option_names.key?(ch)
77
+ end
78
+ end
79
+
80
+
81
+ def execute(argv=ARGV)
82
+ ## parse command-line options
83
+ options, properties = parse_argv(argv, @single_options, @arg_options)
84
+ filenames = argv
85
+ options[?h] = true if properties[:help]
86
+ opts = Object.new
87
+ arr = @option_names.collect { |ch, name| "def #{name}; @#{name}; end\n" }
88
+ opts.instance_eval arr.join
89
+ options.each do |ch, val|
90
+ name = @option_names[ch]
91
+ opts.instance_variable_set("@#{name}", val)
92
+ end
93
+
94
+ ## help, version, enhancer list
95
+ if opts.help || opts.version
96
+ puts version() if opts.version
97
+ puts usage() if opts.help
98
+ puts show_properties() if opts.help
99
+ puts show_enhancers() if opts.help
100
+ return
101
+ end
102
+
103
+ ## include path
104
+ opts.includes.split(/,/).each do |path|
105
+ $: << path
106
+ end if opts.includes
107
+
108
+ ## require library
109
+ opts.requires.split(/,/).each do |library|
110
+ require library
111
+ end if opts.requires
112
+
113
+ ## action
114
+ action = opts.action
115
+ action ||= 'compile' if opts.source
116
+
117
+ ## lang
118
+ lang = opts.lang || 'ruby'
119
+ action ||= 'compile' if opts.lang
120
+
121
+ ## class name of Eruby
122
+ classname = opts.class
123
+ klass = get_classobj(classname, lang)
124
+
125
+ ## kanji code
126
+ $KCODE = opts.kanji if opts.kanji
127
+
128
+ ## read context values from yaml file
129
+ yamlfiles = opts.yamlfiles
130
+ context = load_yamlfiles(yamlfiles, opts)
131
+
132
+ ## properties for engine
133
+ properties[:pattern] = opts.pattern if opts.pattern
134
+ properties[:trim] = false if opts.notrim
135
+ properties[:preamble] = properties[:postamble] = false if opts.bodyonly
136
+
137
+ ## create engine and extend enhancers
138
+ engine = klass.new(nil, properties)
139
+ enhancers = get_enhancers(opts.enhancers)
140
+ enhancers.push(Erubis::EscapeEnhancer) if opts.escape
141
+ enhancers.each do |enhancer|
142
+ engine.extend(enhancer)
143
+ engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
144
+ end
145
+
146
+ ## compile and execute
147
+ val = nil
148
+ if filenames && !filenames.empty?
149
+ filenames.each do |filename|
150
+ test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
151
+ engine.filename = filename
152
+ engine.compile!(File.read(filename))
153
+ print val if val = do_action(action, engine, context, opts)
154
+ end
155
+ else
156
+ engine.filename = '(stdin)'
157
+ engine.compile!($stdin.read())
158
+ print val if val = do_action(action, engine, context, opts)
159
+ end
160
+
161
+ end
162
+
163
+ private
164
+
165
+ def do_action(action, engine, context, opts)
166
+ case action
167
+ when 'compile'
168
+ s = engine.src
169
+ when nil, 'exec', 'execute'
170
+ s = opts.binding ? engine.result(context) : engine.evaluate(context)
171
+ else
172
+ raise "*** internal error"
173
+ end
174
+ return s
175
+ end
176
+
177
+ def usage
178
+ command = File.basename($0)
179
+ s = <<'END'
180
+ erubis - embedded program compiler for multi-language
181
+ Usage: #{command} [..options..] [file ...]
182
+ -h, --help : help
183
+ -v : version
184
+ -x : compiled code
185
+ -T : don't trim spaces around '<% %>'
186
+ -b : body only (no preamble nor postamble)
187
+ -e : escape (equal to '--E Escape')
188
+ -p pattern : embedded pattern (default '<% %>')
189
+ -l lang : compile but no execute (ruby/php/c/java/scheme/perl/js)
190
+ -E enhancer,... : enhancer name (Escape, PercentLine, BiPattern, ...)
191
+ -I path : library include path
192
+ -K kanji : kanji code (euc/sjis/utf8) (default none)
193
+ -f file.yaml : YAML file for context values (read stdin if filename is '-')
194
+ -t : expand tab character in YAML file
195
+ -S : convert mapping key from string to symbol in YAML file
196
+ -B : invoke 'result(binding)' instead of 'evaluate(context)'
197
+
198
+ END
199
+ # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
200
+ # -r library : require library
201
+ # -a : action (compile/execute)
202
+ return s
203
+ end
204
+
205
+ def show_properties
206
+ s = "supported properties:\n"
207
+ %w[(common) ruby php c java scheme perl javascript].each do |lang|
208
+ list = Erubis::Engine.supported_properties
209
+ if lang != '(common)'
210
+ klass = Erubis.const_get("E#{lang}")
211
+ list = klass.supported_properties - list
212
+ end
213
+ s << " * #{lang}\n"
214
+ list.each do |name, default_val, desc|
215
+ s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
216
+ end
217
+ end
218
+ s << "\n"
219
+ return s
220
+ end
221
+
222
+ def show_enhancers
223
+ s = "enhancers:\n"
224
+ list = []
225
+ ObjectSpace.each_object(Module) do |m| list << m end
226
+ list.sort_by { |m| m.name }.each do |m|
227
+ next unless m.name =~ /\AErubis::(.*)Enhancer\z/
228
+ name = $1
229
+ desc = m.desc
230
+ s << (" %-13s : %s\n" % [name, desc])
231
+ end
232
+ return s
233
+ end
234
+
235
+ def version
236
+ release = ('$Release: 2.0.0 $' =~ /([.\d]+)/) && $1
237
+ return release
238
+ end
239
+
240
+ def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
241
+ options = {}
242
+ context = {}
243
+ while argv[0] && argv[0][0] == ?-
244
+ optstr = argv.shift
245
+ optstr = optstr[1, optstr.length-1]
246
+ #
247
+ if optstr[0] == ?- # context
248
+ unless optstr =~ /\A\-([-\w]+)(?:=(.*))?/
249
+ raise CommandOptionError.new("-#{optstr}: invalid context value.")
250
+ end
251
+ name = $1; value = $2
252
+ name = name.gsub(/-/, '_').intern
253
+ #value = value.nil? ? true : YAML.load(value) # error, why?
254
+ value = value.nil? ? true : YAML.load("---\n#{value}\n")
255
+ context[name] = value
256
+ #
257
+ else # options
258
+ while optstr && !optstr.empty?
259
+ optchar = optstr[0]
260
+ optstr[0,1] = ""
261
+ if arg_none.include?(optchar)
262
+ options[optchar] = true
263
+ elsif arg_required.include?(optchar)
264
+ arg = optstr.empty? ? argv.shift : optstr
265
+ unless arg
266
+ mesg = "-#{optchar.chr}: #{@option_args[optchar]} required."
267
+ raise CommandOptionError.new(mesg)
268
+ end
269
+ options[optchar] = arg
270
+ optstr = nil
271
+ elsif arg_optional.include?(optchar)
272
+ arg = optstr.empty? ? true : optstr
273
+ options[optchar] = arg
274
+ optstr = nil
275
+ else
276
+ raise CommandOptionError.new("-#{optchar.chr}: unknown option.")
277
+ end
278
+ end
279
+ end
280
+ #
281
+ end # end of while
282
+
283
+ return options, context
284
+ end
285
+
286
+ def untabify(text, width=8)
287
+ sb = ''
288
+ text.scan(/(.*?)\t/m) do |s, |
289
+ len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
290
+ sb << s << (" " * (width - len % width))
291
+ end
292
+ return $' ? (sb << $') : text
293
+ end
294
+
295
+ def get_classobj(classname, lang)
296
+ unless classname
297
+ classname = lang =~ /\Axml(.*)/ ? "EscapedE#{$1}" : "E#{lang}"
298
+ end
299
+ begin
300
+ klass = Erubis.const_get(classname)
301
+ rescue NameError
302
+ klass = nil
303
+ end
304
+ unless klass
305
+ if lang
306
+ msg = "-l #{lang}: invalid language name (class Erubis::#{classname} not found)."
307
+ else
308
+ msg = "-c #{classname}: invalid class name."
309
+ end
310
+ raise CommandOptionError.new(msg)
311
+ end
312
+ return klass
313
+ end
314
+
315
+ def get_enhancers(enhancer_names)
316
+ return [] unless enhancer_names
317
+ enhancers = []
318
+ shortname = nil
319
+ begin
320
+ enhancer_names.split(/,/).each do |shortname|
321
+ enhancers << Erubis.const_get("#{shortname}Enhancer")
322
+ end
323
+ rescue NameError
324
+ raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-E' to show all enhancers).")
325
+ end
326
+ return enhancers
327
+ end
328
+
329
+ def load_yamlfiles(yamlfiles, opts)
330
+ hash = {}
331
+ return hash unless yamlfiles
332
+ yamlfiles.split(/,/).each do |yamlfile|
333
+ if yamlfile == '-'
334
+ str = $stdin.read()
335
+ else
336
+ test(?f, yamlfile) or raise CommandOptionError.new("#{yamlfile}: file not found.")
337
+ str = File.read(yamlfile)
338
+ end
339
+ str = yamlfile == '-' ? $stdin.read() : File.read(yamlfile)
340
+ str = untabify(str) if opts.untabify
341
+ ydoc = YAML.load(str)
342
+ unless ydoc.is_a?(Hash)
343
+ raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
344
+ end
345
+ convert_mapping_key_from_string_to_symbol(ydoc) if opts.intern
346
+ hash.update(ydoc)
347
+ end
348
+ context = hash
349
+ return context
350
+ end
351
+
352
+ def convert_mapping_key_from_string_to_symbol(ydoc)
353
+ if ydoc.is_a?(Hash)
354
+ ydoc.each do |key, val|
355
+ ydoc[key.intern] = ydoc.delete(key) if key.is_a?(String)
356
+ convert_mapping_key_from_string_to_symbol(val)
357
+ end
358
+ elsif ydoc.is_a?(Array)
359
+ ydoc.each do |val|
360
+ convert_mapping_key_from_string_to_symbol(val)
361
+ end
362
+ end
363
+ return ydoc
364
+ end
365
+
366
+ end
367
+
368
+ end
@@ -0,0 +1,65 @@
1
+ ##
2
+ ## $Rev: 21 $
3
+ ## $Release: 2.0.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+ module Erubis
8
+
9
+ ##
10
+ ## tiny and the simplest implementation of eRuby
11
+ ##
12
+ ## ex.
13
+ ## eruby = TinyEruby.new(File.read('example.rhtml'))
14
+ ## print eruby.src # print ruby code
15
+ ## print eruby.result(binding()) # eval ruby code with Binding object
16
+ ## print eruby.evalute(context) # eval ruby code with context object
17
+ ##
18
+ class TinyEruby
19
+
20
+ def initialize(input)
21
+ @src = compile(input)
22
+ end
23
+ attr_reader :src
24
+
25
+ EMBEDDED_PATTERN = /(.*?)<%(=+|\#)?(.*?)-?%>/m
26
+
27
+ def compile(input)
28
+ src = "_buf = [];" # preamble
29
+ input.scan(EMBEDDED_PATTERN) do |text, indicator, code|
30
+ src << " _buf << '" << escape_text(text) << "';"
31
+ if !indicator # <% %>
32
+ src << code << ";"
33
+ elsif indicator[0] == ?\# # <%# %>
34
+ n = code.count("\n")
35
+ add_stmt(src, "\n" * n)
36
+ else # <%= %>
37
+ src << " _buf << (" << code << ").to_s;"
38
+ end
39
+ end
40
+ rest = $' || input
41
+ src << " _buf << '" << escape_text(rest) << "';"
42
+ src << "\n_buf.join\n" # postamble
43
+ return src
44
+ end
45
+
46
+ def escape_text(text)
47
+ return text.gsub!(/['\\]/, '\\\\\&') || text
48
+ end
49
+
50
+ def result(binding=TOPLEVEL_BINDING)
51
+ eval @src, binding
52
+ end
53
+
54
+ def evaluate(context=Object.new)
55
+ if context.is_a?(Hash)
56
+ obj = Object.new
57
+ context.each do |k, v| obj.instance_variable_set("@#{k}", v) end
58
+ context = obj
59
+ end
60
+ context.instance_eval @src
61
+ end
62
+
63
+ end
64
+
65
+ end