assert2 0.3.2 → 0.3.3

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.
@@ -0,0 +1,87 @@
1
+ require 'test/unit'
2
+
3
+
4
+ module Test; module Unit; module Assertions
5
+
6
+ # Assert that a block raises a given Exception type matching
7
+ # a given message
8
+ #
9
+ # * +types+ - single exception class or array of classes
10
+ # * +matcher+ - Regular Expression to match the inner_text of XML nodes
11
+ # * +diagnostic+ - optional string to add to failure message
12
+ # * +block+ - Ruby statements that should raise an exception
13
+ #
14
+ # Examples:
15
+ # %transclude AssertXPathSuite#test_assert_raise_message_detects_assertion_failure
16
+ #
17
+ # %transclude AssertXPathSuite#test_assert_raise_message_raises_message
18
+ #
19
+ # See: {assert_raise - Don't Just Say "No"}[http://www.oreillynet.com/onlamp/blog/2007/07/assert_raise_on_ruby_dont_just.html]
20
+ #
21
+ def assert_raise_message(types, expected_message, message = nil, &block)
22
+ args = [types].flatten + [message]
23
+ exception = _assert_raise(*args, &block)
24
+ exception_message = exception.message.dup
25
+
26
+ if expected_message.kind_of? String
27
+ exception_message.gsub!(/^\s+/, '') # if we cosmetically strip leading spaces from both the matcher and matchee,
28
+ expected_message.gsub!(/^\s+/, '') # then multi-line assert_flunk messages are easier on the eyes!
29
+ expected_message = Regexp.escape(expected_message)
30
+ end
31
+
32
+ assert message do
33
+ exception_message.match(expected_message)
34
+ end
35
+
36
+ return exception.message
37
+ end
38
+
39
+ # TODO rebuild this
40
+ def deny_raise_message(types, matcher, diagnostic = nil, &block) #:nodoc:
41
+ exception = assert_raise_message(types, //, diagnostic, &block)
42
+
43
+ assert_no_match matcher,
44
+ exception.message,
45
+ [ diagnostic,
46
+ "exception #{ exception.class.name
47
+ } with this message should not raise from block:",
48
+ "\t"+reflect_source(&block).split("\n").join("\n\t")
49
+ ].compact.join("\n")
50
+
51
+ return exception.message
52
+ end
53
+
54
+ def assert_flunk(matcher, message = nil, &block)
55
+ assert_raise_message FlunkError, matcher, message, &block
56
+ end
57
+
58
+ # TODO reinstall ruby-1.9.0 and pass all cross-tests!!
59
+
60
+ def _assert_raise(*args)
61
+ # _wrap_assertion do
62
+ if Module === args.last
63
+ message = ""
64
+ else
65
+ message = args.pop
66
+ end
67
+ exceptions, modules = args, [] # _check_exception_class(args)
68
+
69
+ expected = args.size == 1 ? args.first : args
70
+ actual_exception = nil
71
+ full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
72
+ assert_block(full_message) do
73
+ begin
74
+ yield
75
+ rescue Exception => actual_exception
76
+ break
77
+ end
78
+ false
79
+ end
80
+ full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
81
+ assert_block(full_message) {exceptions.include?(actual_exception.class)}
82
+ actual_exception
83
+ # end
84
+ end
85
+
86
+ end; end; end
87
+
File without changes
@@ -0,0 +1,182 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <title><%= @title %></title>
6
+ <meta http-equiv="content-type" content="text/html; charset=us-ascii" />
7
+ <script type="text/javascript" src="javascript/prototype.js"></script>
8
+ <script type="text/javascript" src="javascript/effects.js"></script>
9
+ <script type="text/javascript" src="javascript/accordion.js"></script>
10
+ <link rel="stylesheet" type="text/css" href="css/default.css" />
11
+ <script type="text/javascript">
12
+ //<![CDATA[
13
+
14
+ var bottomAccordion = 42;
15
+
16
+ function raise(id)
17
+ {
18
+ var anchor = $(id + '_');
19
+ if (anchor) {
20
+ bottomAccordion.activate(anchor.parentNode);
21
+ }
22
+ }
23
+
24
+ Event.observe(window, 'load', loadAccordions, false);
25
+ function loadAccordions() {
26
+ bottomAccordion = new accordion('vertical_container');
27
+
28
+ var anchor = window.location.href.match(/#(.+)$/);
29
+ if (anchor) anchor = anchor[1];
30
+ if (anchor = $(anchor + '_')) {
31
+ bottomAccordion.activate(anchor.parentNode);
32
+ }
33
+ else {
34
+ bottomAccordion.activate($$('#vertical_container .accordion_toggle')[0]);
35
+ }
36
+ }
37
+ //]]>
38
+ </script>
39
+
40
+ <style type="text/css">
41
+ /*<![CDATA[*/
42
+ /* Vertical Accordions */
43
+
44
+ pre { border-width: 10px;
45
+ border-color: #e7e7c9;
46
+ border-style: solid;
47
+ }
48
+
49
+ .accordion_toggle {
50
+ display: block;
51
+ height: 30px;
52
+ width: 680px;
53
+ background: url(images/accordion_toggle.png) no-repeat top right;
54
+ padding: 0 10px 0 10px;
55
+ cursor: index;
56
+ font-weight: normal;
57
+ text-decoration: none;
58
+ outline: none;
59
+ font-family: 'Lucida Grande', Verdana, Arial;
60
+ color: #800;
61
+ cursor: pointer;
62
+ margin: 0 0 0 0;
63
+ }
64
+
65
+ .accordion_toggle_active {
66
+ background: url(images/accordion_toggle_active.png) no-repeat top right;
67
+ color: #FDE;
68
+ }
69
+
70
+ .accordion_content {
71
+ background-color: #ffffff;
72
+ color: #444444;
73
+ overflow: hidden;
74
+ }
75
+
76
+ .accordion_content h2 {
77
+ margin: 15px 0 5px 10px;
78
+ color: #0099FF;
79
+ }
80
+
81
+ .accordion_content p {
82
+ padding: 5px 10px 0 10px;
83
+ }
84
+
85
+ /*
86
+ Horizontal Accordion
87
+ */
88
+
89
+ .horizontal_accordion_toggle {
90
+ /* REQUIRED */
91
+ float: left; /* This make sure it stays horizontal */
92
+ /* REQUIRED */
93
+
94
+ display: block;
95
+ height: 100px;
96
+ width: 30px;
97
+ background: url(images/h_accordion_toggle.png) no-repeat top left #a9d06a;
98
+ color: #ffffff;
99
+ text-decoration: none;
100
+ outline: none;
101
+ border-right: 1px solid #cde99f;
102
+ cursor: pointer;
103
+ margin: 0 0 0 0;
104
+ }
105
+
106
+ .horizontal_accordion_toggle_active {
107
+ background: url(images/h_accordion_toggle_active.png) no-repeat top left #e0542f;
108
+ border-right: 1px solid #f68263;
109
+ }
110
+
111
+ .horizontal_accordion_content {
112
+ /* REQUIRED */
113
+ height: 100px; /* We need to define a height for the accordion as it stretches the width */
114
+ float: left; /* This make sure it stays horizontal */
115
+ /* REQUIRED */
116
+
117
+ overflow: hidden;
118
+ background-color: #ffffff;
119
+ color: #444444;
120
+ }
121
+
122
+ .horizontal_accordion_content p {
123
+ width: 450px;
124
+ /*line-height: 125%;*/
125
+ padding: 5px 10px 15px 10px;
126
+ }
127
+
128
+
129
+ /* Container styling*/
130
+ #horizontal_container {
131
+ margin: 20px auto 20px auto;
132
+ width: 680px;
133
+ height: 100px;
134
+ }
135
+
136
+ /*#vertical_nested_container {
137
+ margin: 20px auto 20px auto;
138
+ width: 620px;
139
+ }*/
140
+
141
+ /*]]>*/
142
+ </style>
143
+ </head>
144
+
145
+ <body style="font-family: Times,serif; background-image: url(images/sky_blue.png); background-repeat: repeat-x;">
146
+ <div style='position: absolute; top: 0px; left: 70%;'>
147
+ <a href="http://validator.w3.org/check/referer">
148
+ <img border='0' height="76" width="72" alt='Validates this page at W3C'
149
+ src="http://assert2.rubyforge.org/the_test_button.png"/>
150
+ </a>
151
+ </div>
152
+
153
+ <div id="container">
154
+
155
+ <h1><code><big style='color: #008;'><%= @title %></big></code></h1>
156
+
157
+ <div id="vertical_container">
158
+ <%= @sauce %>
159
+ </div>
160
+
161
+ <div class="page-footer">
162
+ <p>Accordion is &#169; Copyright 2007 <a href="http://www.stickmanlabs.com"><small>stickmanlabs</small></a> - MIT-style license</p>
163
+ </div>
164
+ </div>
165
+ <br />
166
+ <script type="text/javascript">
167
+ //<![CDATA[
168
+ //
169
+ // You can hide the accordions on page load like this, it maintains accessibility
170
+ //
171
+ // Special thanks go out to Will Shaver @ http://primedigit.com/
172
+ //
173
+ var verticalAccordions = $$('.accordion_toggle');
174
+ verticalAccordions.each(function(accordion) {
175
+ $(accordion.next(0)).setStyle({
176
+ height: '0px'
177
+ });
178
+ });
179
+ //]]>
180
+ </script>
181
+ </body>
182
+ </html>
@@ -0,0 +1,413 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ripper'
4
+ require 'stringio'
5
+ require 'cgi'
6
+ require 'erb'
7
+ require 'optparse'
8
+ require 'pathname'
9
+
10
+ # TODO reflect the banner anchor at generation time, to figure out what to hotlink to
11
+
12
+ class Ripdoc < Ripper::Filter
13
+ HomePath = (Pathname.new(__FILE__).dirname + '../..').expand_path
14
+
15
+ STYLES = {
16
+ CHAR: 'color: brown; font-weight: bolder;',
17
+ const: "color: #FF4F00; font-weight: bolder;",
18
+ backref: "color: #f4f; font-weight: bolder;",
19
+ comment: "font-style: italic; color: #446; font-family: Times; font-size: 110%;",
20
+ # TODO use "font: Times italic 110%" to save space
21
+ embdoc: "background-color: #FFe; font-family: Times; font-size: 133%;",
22
+ embdoc_beg: "display: none;",
23
+ embdoc_end: "display: none;",
24
+ embexpr: "background-color: #ccc;",
25
+ embexpr_delimiter: "background-color: #aaa;",
26
+ gvar: "color: #8f5902; font-weight: bolder;",
27
+ ivar: "color: #240;",
28
+ int: "color: #336600; font-weight: bolder;",
29
+ operator: "font-weight: bolder; font-size: 120%;",
30
+ kw: "color: purple;",
31
+ regexp_delimiter: "background-color: #faf;",
32
+ regexp: "background-color: #fcf;",
33
+ string: "background-color: white;", #dfc
34
+ string_delimiter: "background-color: #cfa;",
35
+ symbol: "color: #066;",
36
+ tstring_content: 'background: url(images/tstring.png) right;',
37
+ tstring_internal: 'background: url(images/tstring.png) right;', # TODO merge these two!
38
+ tregexp_content: 'background: url(images/hot_pink.png);'
39
+ }
40
+
41
+ def self.generate(filename, title)
42
+ @sauce = compile_fragment(File.read(filename))
43
+ @title = title
44
+ @string_background = :tstring_content
45
+ erb = ERB.new((HomePath + 'lib/assert2/ripdoc.html.erb').read, nil, '>')
46
+ xhtml = erb.result(binding())
47
+ xhtml.gsub! /\<pre>\s*\<\/pre>/m, ''
48
+ xhtml.gsub! /\<p>\s*\<\/p>/m, ''
49
+ return xhtml
50
+ end
51
+
52
+ def dequote(attributes)
53
+ return attributes.gsub('&quot;', '"')
54
+ end # TODO complex '"? if we can't it might be a good thing...
55
+
56
+ def enline(line)
57
+ line = CGI.escapeHTML(line)
58
+ return line.gsub( /&lt;a(.*?)&gt;/){ "<a #{dequote($1)}>" }.
59
+ gsub('&lt;/a&gt;', '</a>').
60
+ gsub(/&lt;br\s*\/&gt;/, '<br/>').
61
+ gsub( '&lt;code&gt;', '<code style="font-weight: bolder; font-style: normal;">').
62
+ gsub('&lt;/code&gt;', '</code>').
63
+ gsub( '&lt;em&gt;', '<em>').
64
+ gsub('&lt;/em&gt;', '</em>').
65
+ gsub( '&lt;li&gt;', '<li>').
66
+ gsub('&lt;/li&gt;', '</li>').
67
+ gsub( '&lt;ul&gt;', '<ul>').
68
+ gsub('&lt;/ul&gt;', '</ul>').
69
+ gsub('&amp;mdash;', '&mdash;')
70
+ end
71
+
72
+ def deformat(line, f)
73
+ if line =~ /^\s/ # CONSIDER why the line-height broke??
74
+ f << "</p>" if @owed_p
75
+ f << "<pre style='line-height: 75%;'>\n" unless @owed_pre
76
+ @owed_p = false
77
+ @owed_pre = true
78
+ f << enline(line) << "\n"
79
+ return
80
+ end
81
+
82
+ f << '</pre>' if @owed_pre
83
+ @owed_pre = false
84
+ f << '<p>' unless @owed_p
85
+ @owed_p = true
86
+ f << enline(line)
87
+ end
88
+
89
+ def on_embdoc_beg(tok, f)
90
+ return f if @in_no_doc
91
+ @embdocs = []
92
+ f << "</pre>\n" if @owed_pre
93
+ @owed_pre = false
94
+ return f
95
+ # on_kw tok, f, 'embdoc_beg'
96
+ end
97
+
98
+ def is_no_doc?(tok)
99
+ tok.strip =~ /^\#\!nodoc\!/ or tok.strip =~ /^\#\!no_doc\!/
100
+ end
101
+
102
+ def on_embdoc(tok, f)
103
+ return f if @in_no_doc
104
+
105
+ if is_no_doc? tok
106
+ @in_no_doc = true
107
+ else
108
+ @embdocs << tok
109
+ end
110
+
111
+ return f
112
+ end
113
+
114
+ def on_embdoc_end(tok, f)
115
+ return f if @in_no_doc
116
+ return end_panel(f)
117
+ return f
118
+ end
119
+
120
+ def name_toggle(banner)
121
+ banner = banner.gsub(/<.*?>/, '').
122
+ gsub(/&.*?;/, '').
123
+ scan(/[ _[:alnum:]]/).
124
+ map{|x| x == ' ' ? '_' : x }.
125
+ join.
126
+ gsub(/_+/, '_').
127
+ gsub(/_$/, '')
128
+
129
+ return "<a href='#' name='#{banner}' id='#{banner}_'></a>" # CONSIDER this can't use <a ../> because enline() would mangle it...
130
+ # CONSIDER the _ is due to a bug in libxml - it squeaks at a name and id that are the same -
131
+ # despite that's a common idiom!
132
+ end
133
+
134
+ def end_panel(f)
135
+ if banner = @embdocs.shift # accordion_toggle_active
136
+ f << '<h1 class="accordion_toggle">'
137
+ f << name_toggle(banner)
138
+ f << enline(banner)
139
+ f << '</h1>'
140
+ end
141
+
142
+ f << '<div class="accordion_content">'
143
+ f << '<p>'
144
+ @owed_p = true
145
+ prior = false
146
+
147
+ @embdocs.each do |doc|
148
+ if doc.strip == ''
149
+ f << "</p>\n<p>" if @owed_p
150
+ prior = false
151
+ elsif doc.strip =~ /^\#\!link\!(.*)/ #!link!froot!loop
152
+ target, contents = $1.split('!') # TODO permit a ! in the contents
153
+ puts '#!link!anchor!text tags work best with text after the last bang!' unless contents
154
+ contents ||= ''
155
+ f << "<a href='\##{target}' onclick='raise(\"#{target}\")'>"
156
+ f << enline(contents)
157
+ f << '</a>'
158
+ else
159
+ f << ' ' if prior
160
+ deformat(doc, f)
161
+ prior = true
162
+ end
163
+ end
164
+
165
+ f << '</p>' if @owed_p
166
+ f << '<pre>' unless @owed_pre
167
+ @owed_pre = true
168
+ @embdocs = []
169
+ return f
170
+ end
171
+
172
+ # TODO need a tregexp_content to distinguish them!
173
+
174
+ def span(kode)
175
+ if STYLES[kode.to_sym]
176
+ # class="#{kode}"
177
+ return %Q[<span style="#{STYLES[kode.to_sym]}">]
178
+ else
179
+ return '<span>'
180
+ end
181
+ end
182
+
183
+ def spanit(kode, f, tok)
184
+ @spans_owed ||= 0
185
+ @spans_owed += 1
186
+ f << span(kode) << CGI.escapeHTML(tok)
187
+ end
188
+
189
+ def on_kw(tok, f, klass = 'kw')
190
+ return f if @in_no_doc
191
+ f << span(klass) << CGI.escapeHTML(tok)
192
+ f << '</span>'
193
+ end
194
+
195
+ def on_comment(tok, f)
196
+ if tok.strip =~ /^\#\!end_panel\!/
197
+ f << '</pre>' if @owed_pre
198
+ @owed_pre = false
199
+ f << '</div>'
200
+ return f
201
+ end
202
+
203
+ nodoc = is_no_doc?(tok)
204
+
205
+ if !nodoc and !@in_no_doc and tok.strip !~ /^\s*#\!/
206
+ f << span(:comment) << enline(tok.rstrip) << '</span>'
207
+ on_nl nil, f
208
+ end
209
+
210
+ @in_no_doc ||= nodoc
211
+ @in_no_doc = nil if tok.strip =~ /^\#\!doc\!/
212
+ return f
213
+ end
214
+
215
+ def on_CHAR(tok, f)
216
+ return f if @in_no_doc
217
+ on_kw tok, f, 'CHAR'
218
+ return f
219
+ end
220
+
221
+ # TODO linefeeds inside %w() and possibly ''
222
+ # TODO colorize :"" and :"#{}" correctly
223
+
224
+ def on_default(event, tok, f)
225
+ return f if @in_no_doc
226
+
227
+ if @symbol_begun
228
+ @symbol_begun = false
229
+ f << %Q[#{span(:symbol)}#{CGI.escapeHTML(tok)}</span>]
230
+ elsif tok =~ /^[[:punct:]]+$/
231
+ f << %Q[#{span(:operator)}#{CGI.escapeHTML(tok)}</span>]
232
+ else
233
+ on_kw tok, f, event.to_s.sub(/^on_/, '')
234
+ end
235
+
236
+ return f
237
+ end
238
+
239
+ def finish_one_span(f)
240
+ if @spans_owed > 0
241
+ f << '</span>'
242
+ @spans_owed -= 1
243
+ end
244
+ end
245
+
246
+ def on_tstring_beg(tok, f)
247
+ return f if @in_no_doc
248
+ @spans_owed += 1
249
+ f << span(:string)
250
+ @string_background = :tstring_content
251
+ f << %Q[#{span(:string_delimiter)}#{CGI.escapeHTML(tok)}</span>]
252
+ end
253
+
254
+ def on_tstring_content(tok, f, style = 'tstring_content')
255
+ tok.split(/\n/).each_with_index do |sub_tok, index|
256
+ if index == 0
257
+ on_string_stretch(sub_tok, f, style)
258
+ else
259
+ space, sub_tok = sub_tok.scan(/(\s*)(.*)/).first
260
+ f << space
261
+ on_string_stretch(sub_tok, f, style)
262
+ end
263
+ end
264
+ return f
265
+ end
266
+
267
+ def on_string_stretch(tok, f, klass = 'TODO remove me')
268
+ return f if @in_no_doc
269
+ f << span(@string_background.to_s) << CGI.escapeHTML(tok)
270
+ f << '</span>'
271
+ end
272
+
273
+ # TODO fix end-of-delim bug in // and %w() and %{} etc
274
+
275
+ def on_tstring_end(tok, f)
276
+ return f if @in_no_doc
277
+
278
+ if tok.length > 1
279
+ margin, content, tok = tok.scan(/^(\s*)(.*)(.)$/).first
280
+ f << margin if margin
281
+ on_tstring_content content, f, 'tstring_internal' if content # TODO is this used??
282
+ end
283
+
284
+ f << %Q[#{span(:string_delimiter)}#{CGI.escapeHTML(tok.to_s)}</span>]
285
+ finish_one_span(f)
286
+ return f
287
+ end # TODO report to ripper author the bug where on_tstring_end contains the whole string
288
+
289
+ def on_regexp_beg(tok, f)
290
+ return f if @in_no_doc
291
+ @spans_owed += 1
292
+ f << span(:regexp)
293
+ @string_background = :tregexp_content
294
+ f << %Q[#{span(:regexp_delimiter)}#{CGI.escapeHTML(tok)}</span>]
295
+ end
296
+
297
+ def on_regexp_end(tok, f)
298
+ return f if @in_no_doc
299
+ f << %Q[#{span(:regexp_delimiter)}#{CGI.escapeHTML(tok)}</span>]
300
+ finish_one_span(f)
301
+ return f
302
+ end
303
+
304
+ def on_embexpr_beg(tok, f)
305
+ return f if @in_no_doc
306
+ spanit :embexpr, f, tok
307
+ return f
308
+ end # TODO don't interrupt a span or nothing with a nodoc!
309
+
310
+ # TODO single-line mode for nodoc
311
+
312
+ def on_ignored_nl(tok, f)
313
+ return f if @in_no_doc
314
+ on_nl nil, f
315
+ end
316
+
317
+ def on_nl(tok, f)
318
+ return f if @in_no_doc
319
+ f << "\n"
320
+ end
321
+
322
+ def on_lbrace(tok, f)
323
+ return f if @in_no_doc
324
+ spanit '', f, '' # tok CONSIDER wonder who is actually emitting the { ??
325
+ f << tok
326
+ end
327
+
328
+ def on_rbrace(tok, f)
329
+ return f if @in_no_doc
330
+ f << tok
331
+ finish_one_span(f) # TODO these things might wrap lines!
332
+ return f
333
+ end
334
+
335
+ def on_symbeg(tok, f)
336
+ return f if @in_no_doc
337
+ on_default(:on_symbeg, tok, f)
338
+ @symbol_begun = true
339
+ return f
340
+ end
341
+
342
+ # TODO syntax hilite the inner language of regices? how about XPathics?
343
+ # escapes in strings??
344
+
345
+ def on_ivar(tok, f)
346
+ return f if @in_no_doc
347
+ f << %Q[#{span(:ivar)}#{CGI.escapeHTML(tok)}</span>]
348
+ end
349
+
350
+ attr_accessor :embdocs,
351
+ :in_no_doc,
352
+ :owed_pre,
353
+ :spans_owed
354
+
355
+ def parse(buf, f)
356
+ @spans_owed = 0
357
+ @symbol_begun = false
358
+ super(buf)
359
+ end
360
+
361
+ DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
362
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' +
363
+ "\n"
364
+
365
+ def Ripdoc.compile(f)
366
+ return DOCTYPE +
367
+ '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr"
368
+ ><head>' +
369
+ '</head><body>' + compile_fragment(f) + '</body></html>'
370
+ end
371
+
372
+ def Ripdoc.compile_fragment(f)
373
+ buf = StringIO.new
374
+ parser = Ripdoc.new(f)
375
+ parser.in_no_doc = false
376
+ parser.owed_pre = true
377
+ parser.parse(buf, f)
378
+ result = buf.string
379
+ parser.spans_owed.times{ result += '</span>' }
380
+
381
+ return '<div id="content"><pre>' + result +
382
+ "#{'</pre>' if parser.owed_pre }</div>"
383
+
384
+ end
385
+
386
+ end
387
+
388
+ #~ :on_ident
389
+ #~ :on_const
390
+ #~ :on_semicolon
391
+ #~ :on_op
392
+ #~ :on_int
393
+ #~ :on_comma
394
+ #~ :on_lparen
395
+ #~ :on_rparen
396
+ #~ :on_backref
397
+ #~ :on_period
398
+ #~ :on_lbracket
399
+ #~ :on_rbracket
400
+ #~ :on_rbrace
401
+ #~ :on_qwords_beg
402
+ #~ :on_words_sep
403
+
404
+ class ERB
405
+ attr_accessor :lineno
406
+
407
+ remove_method :result
408
+ def result(b)
409
+ eval(@src, b, (@filename || '(erb)'), (@lineno || 1))
410
+ end
411
+ end
412
+
413
+ system 'rubyw1.9.0 ../../test/ripdoc_suite.rb' if $0 == __FILE__