erubis 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/{ChangeLog → CHANGES} +139 -6
  2. data/MIT-LICENSE +20 -0
  3. data/README.txt +20 -5
  4. data/benchmark/erubybench.rb +465 -229
  5. data/benchmark/erubybench.rhtml +39 -15
  6. data/benchmark/erubybench.yaml +126 -46
  7. data/bin/erubis +2 -2
  8. data/bin/notext +3 -3
  9. data/contrib/action_view_base_rb.patch +23 -0
  10. data/contrib/erubis +466 -308
  11. data/contrib/inline-require +2 -2
  12. data/doc-api/classes/ERB.html +101 -0
  13. data/doc-api/classes/Erubis.html +59 -6
  14. data/doc-api/classes/Erubis/ArrayEnhancer.html +12 -12
  15. data/doc-api/classes/Erubis/Basic/Converter.html +61 -57
  16. data/doc-api/classes/Erubis/BiPatternEnhancer.html +14 -14
  17. data/doc-api/classes/Erubis/CGenerator.html +60 -60
  18. data/doc-api/classes/Erubis/Context.html +125 -29
  19. data/doc-api/classes/Erubis/Converter.html +73 -22
  20. data/doc-api/classes/Erubis/Engine.html +55 -39
  21. data/doc-api/classes/Erubis/EscapeEnhancer.html +6 -6
  22. data/doc-api/classes/Erubis/Evaluator.html +19 -19
  23. data/doc-api/classes/Erubis/Generator.html +16 -10
  24. data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +14 -14
  25. data/doc-api/classes/Erubis/{Helper.html → Helpers.html} +5 -6
  26. data/doc-api/classes/Erubis/Helpers/RailsHelper.html +296 -0
  27. data/doc-api/classes/Erubis/JavaGenerator.html +54 -54
  28. data/doc-api/classes/Erubis/JavascriptGenerator.html +60 -60
  29. data/doc-api/classes/Erubis/Main.html +42 -30
  30. data/doc-api/classes/Erubis/NoCodeEnhancer.html +5 -5
  31. data/doc-api/classes/Erubis/NoTextEnhancer.html +7 -7
  32. data/doc-api/classes/Erubis/OptimizedEruby.html +6 -6
  33. data/doc-api/classes/Erubis/OptimizedGenerator.html +72 -72
  34. data/doc-api/classes/Erubis/OptimizedXmlEruby.html +6 -6
  35. data/doc-api/classes/Erubis/PI/Converter.html +28 -81
  36. data/doc-api/classes/Erubis/PI/Ec.html +6 -6
  37. data/doc-api/classes/Erubis/PI/Ejava.html +6 -6
  38. data/doc-api/classes/Erubis/PI/Ejavascript.html +6 -6
  39. data/doc-api/classes/Erubis/PI/Eperl.html +6 -6
  40. data/doc-api/classes/Erubis/PI/Ephp.html +6 -6
  41. data/doc-api/classes/Erubis/PI/Eruby.html +7 -7
  42. data/doc-api/classes/Erubis/PI/Escheme.html +6 -6
  43. data/doc-api/classes/Erubis/PI/TinyEruby.html +66 -79
  44. data/doc-api/classes/Erubis/PercentLineEnhancer.html +8 -8
  45. data/doc-api/classes/Erubis/PerlGenerator.html +54 -54
  46. data/doc-api/classes/Erubis/PhpGenerator.html +54 -54
  47. data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +21 -21
  48. data/doc-api/classes/Erubis/PrintOutEnhancer.html +30 -30
  49. data/doc-api/classes/Erubis/RubyEvaluator.html +12 -12
  50. data/doc-api/classes/Erubis/RubyGenerator.html +9 -9
  51. data/doc-api/classes/Erubis/SimplifyEnhancer.html +7 -6
  52. data/doc-api/classes/Erubis/StdoutEnhancer.html +12 -12
  53. data/doc-api/classes/Erubis/StringBufferEnhancer.html +13 -13
  54. data/doc-api/classes/Erubis/TinyEruby.html +56 -68
  55. data/doc-api/classes/Erubis/XmlHelper.html +20 -23
  56. data/doc-api/created.rid +1 -1
  57. data/doc-api/files/{__/README_txt.html → README_txt.html} +35 -20
  58. data/doc-api/files/erubis/context_rb.html +2 -2
  59. data/doc-api/files/erubis/converter_rb.html +2 -2
  60. data/doc-api/files/erubis/engine/ec_rb.html +2 -2
  61. data/doc-api/files/erubis/engine/ejava_rb.html +2 -2
  62. data/doc-api/files/erubis/engine/ejavascript_rb.html +2 -2
  63. data/doc-api/files/erubis/engine/enhanced_rb.html +2 -2
  64. data/doc-api/files/erubis/engine/eperl_rb.html +2 -2
  65. data/doc-api/files/erubis/engine/ephp_rb.html +2 -2
  66. data/doc-api/files/erubis/engine/eruby_rb.html +2 -3
  67. data/doc-api/files/erubis/engine/escheme_rb.html +2 -2
  68. data/doc-api/files/erubis/engine/optimized_rb.html +2 -2
  69. data/doc-api/files/erubis/engine_rb.html +2 -2
  70. data/doc-api/files/erubis/enhancer_rb.html +2 -2
  71. data/doc-api/files/erubis/error_rb.html +2 -2
  72. data/doc-api/files/erubis/evaluator_rb.html +2 -2
  73. data/doc-api/files/erubis/generator_rb.html +2 -2
  74. data/doc-api/files/erubis/helper_rb.html +2 -2
  75. data/doc-api/files/erubis/{helper/rails_rb.html → helpers/rails_helper_rb.html} +6 -31
  76. data/doc-api/files/erubis/local-setting_rb.html +2 -2
  77. data/doc-api/files/erubis/main_rb.html +4 -2
  78. data/doc-api/files/erubis/tiny_rb.html +2 -2
  79. data/doc-api/files/erubis_rb.html +2 -2
  80. data/doc-api/fr_class_index.html +3 -3
  81. data/doc-api/fr_file_index.html +2 -2
  82. data/doc-api/fr_method_index.html +142 -147
  83. data/doc-api/index.html +1 -1
  84. data/doc/users-guide.html +387 -218
  85. data/lib/erubis.rb +21 -25
  86. data/lib/erubis/context.rb +34 -4
  87. data/lib/erubis/converter.rb +159 -115
  88. data/lib/erubis/engine.rb +29 -12
  89. data/lib/erubis/engine/ec.rb +2 -2
  90. data/lib/erubis/engine/ejava.rb +2 -2
  91. data/lib/erubis/engine/ejavascript.rb +2 -2
  92. data/lib/erubis/engine/enhanced.rb +2 -2
  93. data/lib/erubis/engine/eperl.rb +2 -2
  94. data/lib/erubis/engine/ephp.rb +2 -2
  95. data/lib/erubis/engine/eruby.rb +5 -6
  96. data/lib/erubis/engine/escheme.rb +2 -2
  97. data/lib/erubis/engine/optimized.rb +2 -2
  98. data/lib/erubis/enhancer.rb +33 -7
  99. data/lib/erubis/error.rb +2 -2
  100. data/lib/erubis/evaluator.rb +2 -2
  101. data/lib/erubis/generator.rb +6 -3
  102. data/lib/erubis/helper.rb +6 -23
  103. data/lib/erubis/helpers/rails_helper.rb +202 -0
  104. data/lib/erubis/local-setting.rb +4 -4
  105. data/lib/erubis/main.rb +90 -35
  106. data/lib/erubis/tiny.rb +57 -52
  107. data/test/assert-text-equal.rb +2 -2
  108. data/test/test-engines.rb +5 -5
  109. data/test/test-erubis.rb +173 -63
  110. data/test/test-main.rb +135 -27
  111. data/test/test-notext.rb +2 -2
  112. data/test/test.rb +2 -2
  113. data/test/testutil.rb +2 -2
  114. metadata +16 -16
  115. data/LGPL +0 -504
  116. data/doc-api/classes/Erubis/Helper/CachedRailsTemplate.html +0 -198
  117. data/doc-api/classes/Erubis/Helper/RailsTemplate.html +0 -366
  118. data/lib/erubis/helper/rails.rb +0 -159
@@ -1,11 +1,17 @@
1
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
- "http://www.w3.org/TR/html4/loose.dtd">
3
- <html>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
5
  <head>
5
- <title>benchmark example</title>
6
+ <title>Stock Prices</title>
6
7
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
8
+ <meta http-equiv="Content-Style-Type" content="text/css" />
9
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
10
+ <link rel="shortcut icon" href="/images/favicon.ico" />
11
+ <link rel="stylesheet" type="text/css" href="/css/style.css" media="all" />
12
+ <script type="text/javascript" src="/js/util.js"></script>
7
13
  <style type="text/css">
8
- <!--
14
+ /*<![CDATA[*/
9
15
 
10
16
  body {
11
17
  color: #333333;
@@ -24,36 +30,54 @@ thead {
24
30
  .even {
25
31
  background-color: #CCCCFF;
26
32
  }
27
- -->
33
+
34
+ .minus {
35
+ color: #FF0000;
36
+ }
37
+
38
+ /*]]>*/
28
39
  </style>
29
40
 
30
41
  </head>
31
42
 
32
43
  <body>
33
44
 
34
- <h1>Companies</h1>
45
+ <h1>Stock Prices</h1>
35
46
 
36
47
  <table>
37
48
  <thead>
38
49
  <tr>
39
- <th>index</th><th>code</th><th>name</th>
50
+ <th>#</th><th>code</th><th>name</th><th>price</th><th>change</th><th>ratio</th>
40
51
  </tr>
41
52
  </thead>
42
53
  <tbody>
43
- <% data.each_with_index do |hash, i| %>
44
- <% n = i + 1 %>
54
+ <%
55
+ n = 0
56
+ for item in list
57
+ n += 1
58
+ %>
45
59
  <tr class="<%= n % 2 == 0 ? 'even' : 'odd' %>">
46
- <td style="text-align: center">
47
- <span><%= n %></span>
60
+ <td style="text-align: center"><%= n %></td>
61
+ <td>
62
+ <a href="/stocks/<%= item['code'] %>"><%= item['code'] %></a>
48
63
  </td>
49
64
  <td>
50
- <a href="/stock/<%= hash[:code] %>"><%= hash[:code] %></a>
65
+ <a href="<%= item['url'] %>"><%= item['name'] %></a>
51
66
  </td>
52
67
  <td>
53
- <a href="<%= hash[:url] %>"><%= hash[:name] %></a>
68
+ <strong><%= item['price'] %></strong>
54
69
  </td>
70
+ <% if item['change'] < 0.0 %>
71
+ <td class="minus"><%= item['change'] %></td>
72
+ <td class="minus"><%= item['ratio'] %></td>
73
+ <% else %>
74
+ <td><%= item['change'] %></td>
75
+ <td><%= item['ratio'] %></td>
76
+ <% end %>
55
77
  </tr>
56
- <% end %>
78
+ <%
79
+ end
80
+ %>
57
81
  </tbody>
58
82
  </table>
59
83
 
@@ -1,61 +1,141 @@
1
- data:
2
- - name: Apple Computer Inc.
3
- url: http://www.apple.com
4
- code: AAPL
5
- - name: Amazon.com Inc
6
- url: http://www.amazon.com
7
- code: AMZN
8
- - name: Sun Microsystems Inc.
9
- url: http://www.sun.com
10
- code: SUNW
11
- - name: Microsoft Corp
12
- url: http://www.microsoft.com
13
- code: MSFT
14
- - name: Adobe Systems Inc.
1
+ list:
2
+ - name: Adobe Systems
3
+ name2: Adobe Systems Inc.
15
4
  url: http://www.adobe.com
16
5
  code: ADBE
17
- - name: Intel Corp.
18
- url: http://www.intel.com
19
- code: INTC
20
- - name: Oracle Corp.
21
- url: http://www.oracle.com
22
- code: ORCL
23
- - name: International Business Machines Corp.
24
- url: http://www.ibm.com
25
- code: IBM
26
- - name: BEA Systems Inc.
6
+ price: 39.26
7
+ change: 0.13
8
+ ratio: 0.33
9
+ - name: Advanced Micro Devices
10
+ name2: Advanced Micro Devices Inc.
11
+ url: http://www.amd.com
12
+ code: AMD
13
+ price: 16.22
14
+ change: 0.17
15
+ ratio: 1.06
16
+ - name: Amazon.com
17
+ name2: Amazon.com Inc
18
+ url: http://www.amazon.com
19
+ code: AMZN
20
+ price: 36.85
21
+ change: -0.23
22
+ ratio: -0.62
23
+ - name: Apple
24
+ name2: Apple Inc.
25
+ url: http://www.apple.com
26
+ code: AAPL
27
+ price: 85.38
28
+ change: -0.87
29
+ ratio: -1.01
30
+ - name: BEA Systems
31
+ name2: BEA Systems Inc.
27
32
  url: http://www.bea.com
28
33
  code: BEAS
29
- - name: eBay Inc.
34
+ price: 12.46
35
+ change: 0.09
36
+ ratio: 0.73
37
+ - name: CA
38
+ name2: CA, Inc.
39
+ url: http://www.ca.com
40
+ code: CA
41
+ price: 24.66
42
+ change: 0.38
43
+ ratio: 1.57
44
+ - name: Cisco Systems
45
+ name2: Cisco Systems Inc.
46
+ url: http://www.cisco.com
47
+ code: CSCO
48
+ price: 26.35
49
+ change: 0.13
50
+ ratio: 0.5
51
+ - name: Dell
52
+ name2: Dell Corp.
53
+ url: http://www.dell.com/
54
+ code: DELL
55
+ price: 23.73
56
+ change: -0.42
57
+ ratio: -1.74
58
+ - name: eBay
59
+ name2: eBay Inc.
30
60
  url: http://www.ebay.com
31
61
  code: EBAY
32
- - name: Yahoo! Inc.
33
- url: http://www.yahoo.com
34
- code: YHOO
35
- - name: Google Inc.
62
+ price: 31.65
63
+ change: -0.8
64
+ ratio: -2.47
65
+ - name: Google
66
+ name2: Google Inc.
36
67
  url: http://www.google.com
37
68
  code: GOOG
38
- - name: Hewlett-Packard Co.
69
+ price: 495.84
70
+ change: 7.75
71
+ ratio: 1.59
72
+ - name: Hewlett-Packard
73
+ name2: Hewlett-Packard Co.
39
74
  url: http://www.hp.com
40
75
  code: HPQ
41
- - name: SAP AG
42
- url: http://www.sap.com
43
- code: SAP
44
- - name: Cisco Systems Inc.
45
- url: http://www.cisco.com
46
- code: CSCO
47
- - name: Juniper Networks, Inc
76
+ price: 41.69
77
+ change: -0.02
78
+ ratio: -0.05
79
+ - name: IBM
80
+ name2: International Business Machines Corp.
81
+ url: http://www.ibm.com
82
+ code: IBM
83
+ price: 97.45
84
+ change: -0.06
85
+ ratio: -0.06
86
+ - name: Intel
87
+ name2: Intel Corp.
88
+ url: http://www.intel.com
89
+ code: INTC
90
+ price: 20.53
91
+ change: -0.07
92
+ ratio: -0.34
93
+ - name: Juniper Networks
94
+ name2: Juniper Networks, Inc
48
95
  url: http://www.juniper.net/
49
96
  code: JNPR
50
- - name: Advanced Micro Devices Inc.
51
- url: http://www.amd.com
52
- code: AMD
53
- - name: Red Hat Inc.
54
- url: http://www.redhat.com
55
- code: RHAT
56
- - name: CA, Inc.
57
- url: http://www.ca.com
58
- code: CA
97
+ price: 18.96
98
+ change: 0.5
99
+ ratio: 2.71
100
+ - name: Microsoft
101
+ name2: Microsoft Corp
102
+ url: http://www.microsoft.com
103
+ code: MSFT
104
+ price: 30.6
105
+ change: 0.15
106
+ ratio: 0.49
107
+ - name: Oracle
108
+ name2: Oracle Corp.
109
+ url: http://www.oracle.com
110
+ code: ORCL
111
+ price: 17.15
112
+ change: 0.17
113
+ ratio: 1.0
114
+ - name: SAP
115
+ name2: SAP AG
116
+ url: http://www.sap.com
117
+ code: SAP
118
+ price: 46.2
119
+ change: -0.16
120
+ ratio: -0.35
59
121
  - name: Seagate Technology
122
+ name2: Seagate Technology
60
123
  url: http://www.seagate.com/
61
124
  code: STX
125
+ price: 27.35
126
+ change: -0.36
127
+ ratio: -1.3
128
+ - name: Sun Microsystems
129
+ name2: Sun Microsystems Inc.
130
+ url: http://www.sun.com
131
+ code: SUNW
132
+ price: 6.33
133
+ change: -0.01
134
+ ratio: -0.16
135
+ - name: Yahoo
136
+ name2: Yahoo! Inc.
137
+ url: http://www.yahoo.com
138
+ code: YHOO
139
+ price: 28.04
140
+ change: -0.17
141
+ ratio: -0.6
data/bin/erubis CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  ###
4
4
  ### $Rev: 10 $
5
- ### $Release: 2.1.0 $
6
- ### copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ### $Release: 2.2.0 $
6
+ ### copyright(c) 2006-2007 kuwata-lab all rights reserved.
7
7
  ###
8
8
 
9
9
  require 'erubis/main'
data/bin/notext CHANGED
@@ -4,8 +4,8 @@
4
4
  ### notext - retrieve embedded code from eRuby, PHP, and so on
5
5
  ###
6
6
  ### $Rev$
7
- ### $Release: 2.1.0 $
8
- ### copyright(c) 2006 kuwata-lab all rights reserved.
7
+ ### $Release: 2.2.0 $
8
+ ### copyright(c) 2006-2007 kuwata-lab all rights reserved.
9
9
  ###
10
10
 
11
11
  require 'erubis'
@@ -93,7 +93,7 @@ end
93
93
 
94
94
  ## help message
95
95
  if opt_help || opt_version
96
- version = ('$Release: 2.1.0 $' =~ /[\.\d]+/) && $&
96
+ version = ('$Release: 2.2.0 $' =~ /[\.\d]+/) && $&
97
97
  puts version if opt_version
98
98
  puts help() if opt_help
99
99
  exit(0)
@@ -0,0 +1,23 @@
1
+ --- action_view/base.rb (original)
2
+ +++ action_view/base.rb (working copy)
3
+ @@ -445,6 +445,11 @@
4
+ end
5
+ end
6
+
7
+ + # convert template into ruby code
8
+ + def convert_template_into_ruby_code(template)
9
+ + ERB.new(template, nil, @@erb_trim_mode).src
10
+ + end
11
+ +
12
+ # Create source code for given template
13
+ def create_template_source(extension, template, render_symbol, locals)
14
+ if template_requires_setup?(extension)
15
+ @@ -458,7 +463,7 @@
16
+ "update_page do |page|\n#{template}\nend"
17
+ end
18
+ else
19
+ - body = ERB.new(template, nil, @@erb_trim_mode).src
20
+ + body = convert_template_into_ruby_code(template)
21
+ end
22
+
23
+ @@template_args[render_symbol] ||= {}
@@ -2,36 +2,29 @@
2
2
 
3
3
  ###
4
4
  ### $Rev: 10 $
5
- ### $Release: 2.1.0 $
6
- ### copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ### $Release: 2.2.0 $
6
+ ### copyright(c) 2006-2007 kuwata-lab all rights reserved.
7
7
  ###
8
8
 
9
9
  #--begin of require 'erubis/main'
10
10
  ###
11
- ### $Rev: 41 $
12
- ### $Release: 2.1.0 $
13
- ### copyright(c) 2006 kuwata-lab all rights reserved.
11
+ ### $Rev: 65 $
12
+ ### $Release: 2.2.0 $
13
+ ### copyright(c) 2006-2007 kuwata-lab all rights reserved.
14
14
  ###
15
15
 
16
16
  require 'yaml'
17
17
  #--begin of require 'erubis'
18
18
  ##
19
- ## $Rev: 36 $
20
- ## $Release: 2.1.0 $
21
- ## copyright(c) 2006 kuwata-lab all rights reserved.
19
+ ## $Rev: 59 $
20
+ ## $Release: 2.2.0 $
21
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
22
22
  ##
23
23
 
24
24
  ##
25
25
  ## an implementation of eRuby
26
26
  ##
27
- ## * class Eruby - normal eRuby class
28
- ## * class XmlEruby - eRuby class which escape '&<>"' into '&amp;&lt;&gt;&quot;'
29
- ## * module StdoutEnhancer - use $stdout instead of String as output
30
- ## * module PrintEnhancer - enable to write print statement in <% ... %>
31
- ## * class OptimizedEruby - optimized Eruby class faster than FastEruby
32
- ## * class OptimizedXmlEruby - optimized XmlEruby class faster than FastXmlEruby
33
- ##
34
- ## example:
27
+ ## ex.
35
28
  ## input = <<'END'
36
29
  ## <ul>
37
30
  ## <% for item in @list %>
@@ -41,25 +34,24 @@ require 'yaml'
41
34
  ## </ul>
42
35
  ## END
43
36
  ## list = ['<aaa>', 'b&b', '"ccc"']
44
- ## eruby = Erubis::Eruby.new()
45
- ## code = eruby.convert(input)
37
+ ## eruby = Erubis::Eruby.new(input)
46
38
  ## puts "--- code ---"
47
- ## puts code
39
+ ## puts eruby.src
48
40
  ## puts "--- result ---"
49
- ## context = Object.new
50
- ## context.instance_variable_set("@list", list)
51
- ## puts context.instance_eval(code)
52
- ## # or @list = list; puts eval(code, binding())
41
+ ## context = Erubis::Context.new() # or new(:list=>list)
42
+ ## context[:list] = list
43
+ ## puts eruby.evaluate(context)
53
44
  ##
54
45
  ## result:
55
46
  ## --- source ---
56
- ## _buf = ""; _buf << " <ul>\n"
57
- ## for item in list
58
- ## _buf << " <li>"; _buf << ( item ).to_s; _buf << "\n"
59
- ## _buf << " "; _buf << Erubis::XmlEruby.escape( item ); _buf << "</li>\n"
60
- ## end
61
- ## _buf << " </ul>\n"
62
- ## _buf
47
+ ## _buf = ''; _buf << '<ul>
48
+ ## '; for item in @list
49
+ ## _buf << ' <li>'; _buf << ( item ).to_s; _buf << '
50
+ ## '; _buf << ' '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</li>
51
+ ## '; end
52
+ ## _buf << '</ul>
53
+ ## ';
54
+ ## _buf.to_s
63
55
  ## --- result ---
64
56
  ## <ul>
65
57
  ## <li><aaa>
@@ -72,19 +64,23 @@ require 'yaml'
72
64
  ##
73
65
 
74
66
 
67
+ module Erubis
68
+ VERSION = ('$Release: 2.2.0 $' =~ /([.\d]+)/) && $1
69
+ end
70
+
75
71
  #--begin of require 'erubis/engine'
76
72
  ##
77
- ## $Rev: 32 $
78
- ## $Release: 2.1.0 $
79
- ## copyright(c) 2006 kuwata-lab all rights reserved.
73
+ ## $Rev: 55 $
74
+ ## $Release: 2.2.0 $
75
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
80
76
  ##
81
77
 
82
78
 
83
79
  #--begin of require 'erubis/generator'
84
80
  ##
85
- ## $Rev: 32 $
86
- ## $Release: 2.1.0 $
87
- ## copyright(c) 2006 kuwata-lab all rights reserved.
81
+ ## $Rev: 42 $
82
+ ## $Release: 2.2.0 $
83
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
88
84
  ##
89
85
 
90
86
  #--begin of require 'abstract'
@@ -168,6 +164,9 @@ end
168
164
  module Erubis
169
165
 
170
166
 
167
+ ##
168
+ ## code generator, called by Converter module
169
+ ##
171
170
  module Generator
172
171
 
173
172
  def self.supported_properties() # :nodoc:
@@ -243,9 +242,9 @@ end
243
242
  #--end of require 'erubis/generator'
244
243
  #--begin of require 'erubis/converter'
245
244
  ##
246
- ## $Rev: 37 $
247
- ## $Release: 2.1.0 $
248
- ## copyright(c) 2006 kuwata-lab all rights reserved.
245
+ ## $Rev: 60 $
246
+ ## $Release: 2.2.0 $
247
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
249
248
  ##
250
249
 
251
250
  #--already included require 'abstract'
@@ -285,6 +284,36 @@ module Erubis
285
284
 
286
285
  protected
287
286
 
287
+ ##
288
+ ## detect spaces at beginning of line
289
+ ##
290
+ def detect_spaces_at_bol(text, is_bol)
291
+ lspace = nil
292
+ if text.empty?
293
+ lspace = "" if is_bol
294
+ elsif text[-1] == ?\n
295
+ lspace = ""
296
+ else
297
+ rindex = text.rindex(?\n)
298
+ if rindex
299
+ s = text[rindex+1..-1]
300
+ if s =~ /\A[ \t]*\z/
301
+ lspace = s
302
+ #text = text[0..rindex]
303
+ text[rindex+1..-1] = ''
304
+ end
305
+ else
306
+ if is_bol && text =~ /\A[ \t]*\z/
307
+ #lspace = text
308
+ #text = nil
309
+ lspace = text.dup
310
+ text[0..-1] = ''
311
+ end
312
+ end
313
+ end
314
+ return lspace
315
+ end
316
+
288
317
  ##
289
318
  ## (abstract) convert input to code
290
319
  ##
@@ -316,57 +345,65 @@ module Erubis
316
345
 
317
346
  def init_converter(properties={})
318
347
  super(properties)
319
- @pattern = properties[:pattern]
320
- @trim = properties[:trim] != false
348
+ @pattern = properties[:pattern]
349
+ @trim = properties[:trim] != false
321
350
  end
322
351
 
323
- #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
324
- DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
352
+ protected
325
353
 
326
354
  ## return regexp of pattern to parse eRuby script
327
- def pattern_regexp(pattern=@pattern)
328
- if pattern.nil? || pattern == '<% %>'
329
- return DEFAULT_REGEXP
330
- else
331
- prefix, postfix = pattern.split()
332
- #return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
333
- return /(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
334
- end
355
+ def pattern_regexp(pattern)
356
+ prefix, postfix = pattern.split() # '<% %>' => '<%', '%>'
357
+ #return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
358
+ #return /(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
359
+ return /#{prefix}(=+|-|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
335
360
  end
336
- protected :pattern_regexp
361
+ module_function :pattern_regexp
362
+
363
+ #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
364
+ #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
365
+ #DEFAULT_REGEXP = /<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
366
+ DEFAULT_REGEXP = pattern_regexp('<% %>')
367
+
368
+ public
337
369
 
338
370
  def convert_input(src, input)
339
- regexp = pattern_regexp(@pattern)
371
+ pat = @pattern
372
+ regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat)
340
373
  pos = 0
341
- input.scan(regexp) do |lspace, indicator, code, rspace|
374
+ is_bol = true # is beginning of line
375
+ input.scan(regexp) do |indicator, code, rspace|
342
376
  match = Regexp.last_match()
343
- index = match.begin(0)
344
- text = input[pos, index - pos]
345
- pos = match.end(0)
346
- add_text(src, text)
377
+ len = match.begin(0) - pos
378
+ text = input[pos, len]
379
+ pos = match.end(0)
380
+ ch = indicator ? indicator[0] : nil
381
+ lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
382
+ is_bol = rspace ? true : false
383
+ add_text(src, text) if text && !text.empty?
347
384
  ## * when '<%= %>', do nothing
348
385
  ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
349
- if !indicator # <% %>
386
+ if ch == ?= # <%= %>
387
+ add_text(src, lspace) if lspace
388
+ add_expr(src, code, indicator)
389
+ add_text(src, rspace) if rspace
390
+ elsif ch == ?\# # <%# %>
391
+ n = code.count("\n") + (rspace ? 1 : 0)
350
392
  if @trim && lspace && rspace
351
- add_stmt(src, "#{lspace}#{code}#{rspace}")
393
+ add_stmt(src, "\n" * n)
352
394
  else
353
395
  add_text(src, lspace) if lspace
354
- add_stmt(src, code)
396
+ add_stmt(src, "\n" * n)
355
397
  add_text(src, rspace) if rspace
356
398
  end
357
- elsif indicator[0] == ?\# # <%# %>
358
- n = code.count("\n") + (rspace ? 1 : 0)
399
+ else # <% %>
359
400
  if @trim && lspace && rspace
360
- add_stmt(src, "\n" * n)
401
+ add_stmt(src, "#{lspace}#{code}#{rspace}")
361
402
  else
362
403
  add_text(src, lspace) if lspace
363
- add_stmt(src, "\n" * n)
404
+ add_stmt(src, code)
364
405
  add_text(src, rspace) if rspace
365
406
  end
366
- else # <%= %>
367
- add_text(src, lspace) if lspace
368
- add_expr(src, code, indicator)
369
- add_text(src, rspace) if rspace
370
407
  end
371
408
  end
372
409
  rest = $' || input # add input when no matched
@@ -415,9 +452,9 @@ module Erubis
415
452
 
416
453
  def init_converter(properties={})
417
454
  super(properties)
418
- @trim = !(properties[:trim] == false)
455
+ @trim = properties.fetch(:trim, true)
419
456
  @pi = properties[:pi] if properties[:pi]
420
- @embchar = properties[:embchar] || '@'
457
+ @embchar = properties[:embchar] || '@'
421
458
  @pattern = properties[:pattern]
422
459
  @pattern = '<% %>' if @pattern.nil? #|| @pattern == true
423
460
  end
@@ -430,60 +467,106 @@ module Erubis
430
467
  protected
431
468
 
432
469
  def convert_input(codebuf, input)
433
- parse_stmts(codebuf, input)
434
- #parse_stmts2(codebuf, input)
435
- end
436
-
437
- def parse_stmts(codebuf, input)
438
- #regexp = pattern_regexp(@pattern)
439
- @pi ||= 'e'
440
- @stmt_pattern ||= /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
441
- pos = 0
442
- input.scan(@stmt_pattern) do |lspace, pi_arg, code, rspace|
443
- match = Regexp.last_match
444
- index = match.begin(0)
445
- text = input[pos, index - pos]
446
- pos = match.end(0)
447
- parse_exprs(codebuf, text) # unless text.empty?
448
- if @trim && lspace && rspace
449
- add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
450
- else
451
- add_text(codebuf, lspace)
452
- add_pi_stmt(codebuf, code, pi_arg)
453
- add_text(codebuf, rspace)
454
- end
455
- end
456
- rest = $' || input
457
- parse_exprs(codebuf, rest)
458
- end
459
-
460
- def parse_exprs(codebuf, input)
461
- unless @expr_pattern
470
+ unless @regexp
471
+ @pi ||= 'e'
462
472
  ch = Regexp.escape(@embchar)
463
473
  if @pattern
464
474
  left, right = @pattern.split(' ')
465
- @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
475
+ @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
466
476
  else
467
- @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
477
+ @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
468
478
  end
469
479
  end
480
+ #
481
+ is_bol = true
470
482
  pos = 0
471
- input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
472
- indicator = indicator1 || indicator2
473
- code = code1 || code2
483
+ input.scan(@regexp) do |pi_arg, stmt, rspace,
484
+ indicator1, expr1, indicator2, expr2|
474
485
  match = Regexp.last_match
475
- index = match.begin(0)
476
- text = input[pos, index - pos]
486
+ len = match.begin(0) - pos
487
+ text = input[pos, len]
477
488
  pos = match.end(0)
489
+ lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil
490
+ is_bol = stmt && rspace ? true : false
478
491
  add_text(codebuf, text) # unless text.empty?
479
- add_pi_expr(codebuf, code, indicator)
492
+ #
493
+ if stmt
494
+ if @trim && lspace && rspace
495
+ add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg)
496
+ else
497
+ add_text(codebuf, lspace) if lspace
498
+ add_pi_stmt(codebuf, stmt, pi_arg)
499
+ add_text(codebuf, rspace) if rspace
500
+ end
501
+ else
502
+ add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2)
503
+ end
480
504
  end
481
505
  rest = $' || input
482
506
  add_text(codebuf, rest)
483
507
  end
484
508
 
509
+ #--
510
+ #def convert_input(codebuf, input)
511
+ # parse_stmts(codebuf, input)
512
+ # #parse_stmts2(codebuf, input)
513
+ #end
514
+ #
515
+ #def parse_stmts(codebuf, input)
516
+ # #regexp = pattern_regexp(@pattern)
517
+ # @pi ||= 'e'
518
+ # @stmt_pattern ||= /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
519
+ # is_bol = true
520
+ # pos = 0
521
+ # input.scan(@stmt_pattern) do |pi_arg, code, rspace|
522
+ # match = Regexp.last_match
523
+ # len = match.begin(0) - pos
524
+ # text = input[pos, len]
525
+ # pos = match.end(0)
526
+ # lspace = detect_spaces_at_bol(text, is_bol)
527
+ # is_bol = rspace ? true : false
528
+ # parse_exprs(codebuf, text) # unless text.empty?
529
+ # if @trim && lspace && rspace
530
+ # add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
531
+ # else
532
+ # add_text(codebuf, lspace)
533
+ # add_pi_stmt(codebuf, code, pi_arg)
534
+ # add_text(codebuf, rspace)
535
+ # end
536
+ # end
537
+ # rest = $' || input
538
+ # parse_exprs(codebuf, rest)
539
+ #end
540
+ #
541
+ #def parse_exprs(codebuf, input)
542
+ # unless @expr_pattern
543
+ # ch = Regexp.escape(@embchar)
544
+ # if @pattern
545
+ # left, right = @pattern.split(' ')
546
+ # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
547
+ # else
548
+ # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
549
+ # end
550
+ # end
551
+ # pos = 0
552
+ # input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
553
+ # indicator = indicator1 || indicator2
554
+ # code = code1 || code2
555
+ # match = Regexp.last_match
556
+ # len = match.begin(0) - pos
557
+ # text = input[pos, len]
558
+ # pos = match.end(0)
559
+ # add_text(codebuf, text) # unless text.empty?
560
+ # add_pi_expr(codebuf, code, indicator)
561
+ # end
562
+ # rest = $' || input
563
+ # add_text(codebuf, rest)
564
+ #end
565
+ #++
566
+
485
567
  def add_pi_stmt(codebuf, code, pi_arg) # :nodoc:
486
568
  case pi_arg
569
+ when nil ; add_stmt(codebuf, code)
487
570
  when 'header' ; @header = code
488
571
  when 'footer' ; @footer = code
489
572
  when 'comment'; add_stmt(codebuf, "\n" * code.count("\n"))
@@ -494,57 +577,17 @@ module Erubis
494
577
 
495
578
  def add_pi_expr(codebuf, code, indicator) # :nodoc:
496
579
  case indicator
497
- when nil, '', '==' # @{...}@ or <%== ... %>
580
+ when nil, '', '==' # @{...}@ or <%== ... %>
498
581
  @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
499
- when '!', '=' # @!{...}@ or <%= ... %>
582
+ when '!', '=' # @!{...}@ or <%= ... %>
500
583
  @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
501
- when '!!', '===' # @!!{...}@ or <%=== ... %>
584
+ when '!!', '===' # @!!{...}@ or <%=== ... %>
502
585
  add_expr_debug(codebuf, code)
503
586
  else
504
587
  # ignore
505
588
  end
506
589
  end
507
590
 
508
- ## (obsolete) equivarent to parse_stmts(), but a little slower than it.
509
- def parse_stmts2(codebuf, input) # :nodoc:
510
- #regexp = pattern_regexp(@pattern)
511
- @pi ||= 'e'
512
- unless @embedded_pattern
513
- ch = Regexp.escape(@embchar)
514
- if @pattern
515
- left, right = @pattern.split(' ')
516
- @embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
517
- else
518
- @embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
519
- end
520
- end
521
- pos = 0
522
- input.scan(@embedded_pattern) do |lspace, pi_arg, stmt, rspace,
523
- indicator1, expr1, indicator2, expr2|
524
- match = Regexp.last_match
525
- index = match.begin(0)
526
- text = input[pos, index - pos]
527
- pos = match.end(0)
528
- add_text(codebuf, text) # unless text.empty?
529
- if stmt
530
- code = stmt
531
- if @trim && lspace && rspace
532
- add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
533
- else
534
- add_text(codebuf, lspace)
535
- add_pi_stmt(codebuf, code, pi_arg)
536
- add_text(codebuf, rspace)
537
- end
538
- else
539
- code = expr1 || expr2
540
- indicator = indicator1 || indicator2
541
- add_pi_expr(codebuf, code, indicator)
542
- end
543
- end
544
- rest = $' || input
545
- add_text(codebuf, rest)
546
- end
547
-
548
591
  end
549
592
 
550
593
 
@@ -553,15 +596,15 @@ end
553
596
  #--begin of require 'erubis/evaluator'
554
597
  ##
555
598
  ## $Rev: 32 $
556
- ## $Release: 2.1.0 $
557
- ## copyright(c) 2006 kuwata-lab all rights reserved.
599
+ ## $Release: 2.2.0 $
600
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
558
601
  ##
559
602
 
560
603
  #--begin of require 'erubis/error'
561
604
  ##
562
605
  ## $Rev: 32 $
563
- ## $Release: 2.1.0 $
564
- ## copyright(c) 2006 kuwata-lab all rights reserved.
606
+ ## $Release: 2.2.0 $
607
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
565
608
  ##
566
609
 
567
610
  module Erubis
@@ -585,9 +628,9 @@ end
585
628
  #--end of require 'erubis/error'
586
629
  #--begin of require 'erubis/context'
587
630
  ##
588
- ## $Rev: 32 $
589
- ## $Release: 2.1.0 $
590
- ## copyright(c) 2006 kuwata-lab all rights reserved.
631
+ ## $Rev: 59 $
632
+ ## $Release: 2.2.0 $
633
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
591
634
  ##
592
635
 
593
636
 
@@ -615,6 +658,7 @@ module Erubis
615
658
  ## print eruby.evaluate(context)
616
659
  ##
617
660
  class Context
661
+ include Enumerable
618
662
 
619
663
  def initialize(hash=nil)
620
664
  hash.each do |name, value|
@@ -631,7 +675,36 @@ module Erubis
631
675
  end
632
676
 
633
677
  def keys
634
- return instance_variables.collect { |name| name[1,name.length-1] }
678
+ return instance_variables.collect { |name| name[1..-1] }
679
+ end
680
+
681
+ def each
682
+ instance_variables.each do |name|
683
+ key = name[1..-1]
684
+ value = instance_variable_get(name)
685
+ yield(key, value)
686
+ end
687
+ end
688
+
689
+ def to_hash
690
+ hash = {}
691
+ self.keys.each { |key| hash[key] = self[key] }
692
+ return hash
693
+ end
694
+
695
+ def update(context_or_hash)
696
+ arg = context_or_hash
697
+ if arg.is_a?(Hash)
698
+ arg.each do |key, val|
699
+ self[key] = val
700
+ end
701
+ else
702
+ arg.instance_variables.each do |varname|
703
+ key = varname[1..-1]
704
+ val = arg.instance_variable_get(varname)
705
+ self[key] = val
706
+ end
707
+ end
635
708
  end
636
709
 
637
710
  end
@@ -718,11 +791,6 @@ module Erubis
718
791
  #include Converter
719
792
  #include Generator
720
793
 
721
- # convert input string and set it to @src
722
- def convert!(input)
723
- @src = convert(input)
724
- end
725
-
726
794
  def initialize(input=nil, properties={})
727
795
  #@input = input
728
796
  init_generator(properties)
@@ -731,12 +799,34 @@ module Erubis
731
799
  @src = convert(input) if input
732
800
  end
733
801
 
734
- ## load file and create engine object
802
+
803
+ ##
804
+ ## convert input string and set it to @src
805
+ ##
806
+ def convert!(input)
807
+ @src = convert(input)
808
+ end
809
+
810
+
811
+ ##
812
+ ## load file, write cache file, and return engine object.
813
+ ## this method create cache file (filename + '.cache') automatically.
814
+ ##
735
815
  def self.load_file(filename, properties={})
736
- input = File.open(filename, 'rb') { |f| f.read }
737
- input.untaint # is it ok?
816
+ cachename = filename + '.cache'
738
817
  properties[:filename] = filename
739
- engine = self.new(input, properties)
818
+ if test(?f, cachename) && File.mtime(filename) <= File.mtime(cachename)
819
+ engine = self.new(nil, properties)
820
+ engine.src = File.read(cachename)
821
+ else
822
+ input = File.open(filename, 'rb') { |f| f.read }
823
+ engine = self.new(input, properties)
824
+ File.open(cachename, 'w') do |f|
825
+ f.flock(File::LOCK_EX)
826
+ f.write(engine.src)
827
+ end
828
+ end
829
+ engine.src.untaint # ok?
740
830
  return engine
741
831
  end
742
832
 
@@ -802,9 +892,9 @@ end
802
892
  #require 'erubis/context'
803
893
  #--begin of require 'erubis/helper'
804
894
  ##
805
- ## $Rev: 21 $
806
- ## $Release: 2.1.0 $
807
- ## copyright(c) 2006 kuwata-lab all rights reserved.
895
+ ## $Rev: 64 $
896
+ ## $Release: 2.2.0 $
897
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
808
898
  ##
809
899
 
810
900
 
@@ -825,28 +915,11 @@ module Erubis
825
915
  "'" => '&#039;',
826
916
  }
827
917
 
828
- def escape_xml(obj)
829
- #table = ESCAPE_TABLE
830
- #obj.to_s.gsub(/[&<>"]/) { |s| table[s] } # or /[&<>"']/
831
- obj.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/
832
- #obj.to_s.gsub(SCAN_REGEXP) { |s| ESCAPE_TABLE[s] }
833
- #obj.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
918
+ def escape_xml(value)
919
+ value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/
920
+ #value.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
834
921
  end
835
922
 
836
- #--
837
- #def escape_xml(obj)
838
- # str = obj.to_s.dup
839
- # #str = obj.to_s
840
- # #str = str.dup if obj.__id__ == str.__id__
841
- # str.gsub!(/&/, '&amp;')
842
- # str.gsub!(/</, '&lt;')
843
- # str.gsub!(/>/, '&gt;')
844
- # str.gsub!(/"/, '&quot;')
845
- # str.gsub!(/'/, '&#039;')
846
- # return str
847
- #end
848
- #++
849
-
850
923
  alias h escape_xml
851
924
  alias html_escape escape_xml
852
925
 
@@ -857,9 +930,9 @@ end
857
930
  #--end of require 'erubis/helper'
858
931
  #--begin of require 'erubis/enhancer'
859
932
  ##
860
- ## $Rev: 32 $
861
- ## $Release: 2.1.0 $
862
- ## copyright(c) 2006 kuwata-lab all rights reserved.
933
+ ## $Rev: 60 $
934
+ ## $Release: 2.2.0 $
935
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
863
936
  ##
864
937
 
865
938
 
@@ -1072,7 +1145,7 @@ module Erubis
1072
1145
 
1073
1146
  def add_postamble(src)
1074
1147
  src << "\n" unless src[-1] == ?\n
1075
- src << "_buf\n"
1148
+ src << "_buf.to_s\n"
1076
1149
  end
1077
1150
 
1078
1151
  end
@@ -1101,6 +1174,31 @@ module Erubis
1101
1174
  end
1102
1175
 
1103
1176
 
1177
+ #--
1178
+ ###
1179
+ ### set buffer variable name to '_erbout' as well as '_buf'
1180
+ ###
1181
+ ### this is only for Eruby.
1182
+ ###
1183
+ #module ErboutEnhancer
1184
+ #
1185
+ # def self.desc # :nodoc:
1186
+ # "set buffer name '_erbout' as well as '_buf'"
1187
+ # end
1188
+ #
1189
+ # def add_preamble(src)
1190
+ # src << "_erbout = _buf = '';"
1191
+ # end
1192
+ #
1193
+ # def add_postamble(src)
1194
+ # src << "\n" unless src[-1] == ?\n
1195
+ # src << "_buf.to_s\n"
1196
+ # end
1197
+ #
1198
+ #end
1199
+ #++
1200
+
1201
+
1104
1202
  ##
1105
1203
  ## remove text and leave code, especially useful when debugging.
1106
1204
  ##
@@ -1181,9 +1279,10 @@ module Erubis
1181
1279
  #regexp = pattern_regexp(@pattern)
1182
1280
  pos = 0
1183
1281
  input.scan(SIMPLE_REGEXP) do |indicator, code|
1184
- index = Regexp.last_match.begin(0)
1185
- text = input[pos, index - pos]
1186
- pos = index + $&.length()
1282
+ match = Regexp.last_match
1283
+ index = match.begin(0)
1284
+ text = input[pos, index - pos]
1285
+ pos = match.end(0)
1187
1286
  add_text(src, text)
1188
1287
  if !indicator # <% %>
1189
1288
  add_stmt(src, code)
@@ -1381,14 +1480,13 @@ end
1381
1480
  #require 'erubis/tiny'
1382
1481
  #--begin of require 'erubis/engine/eruby'
1383
1482
  ##
1384
- ## $Rev: 33 $
1385
- ## $Release: 2.1.0 $
1386
- ## copyright(c) 2006 kuwata-lab all rights reserved.
1483
+ ## $Rev: 54 $
1484
+ ## $Release: 2.2.0 $
1485
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
1387
1486
  ##
1388
1487
 
1389
1488
  #--already included require 'erubis/engine'
1390
1489
  #--already included require 'erubis/enhancer'
1391
- #--already included require 'abstract'
1392
1490
 
1393
1491
 
1394
1492
  module Erubis
@@ -1399,8 +1497,8 @@ module Erubis
1399
1497
  ##
1400
1498
  module RubyGenerator
1401
1499
  include Generator
1402
- #include StringBufferEnhancer
1403
- include ArrayBufferEnhancer
1500
+ #include ArrayBufferEnhancer
1501
+ include StringBufferEnhancer
1404
1502
 
1405
1503
  def init_generator(properties={})
1406
1504
  super
@@ -1510,22 +1608,22 @@ end
1510
1608
 
1511
1609
  #--begin of require 'erubis/local-setting'
1512
1610
  ##
1513
- ## $Rev: 13 $
1514
- ## $Release: 2.1.0 $
1515
- ## copyright(c) 2006 kuwata-lab all rights reserved.
1611
+ ## $Rev: 42 $
1612
+ ## $Release: 2.2.0 $
1613
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
1516
1614
  ##
1517
1615
 
1518
1616
  ##
1519
1617
  ## you can add site-local settings here.
1520
- ## this files is 'require'd by erubis.rb
1618
+ ## this files is required by erubis.rb
1521
1619
  ##
1522
1620
  #--end of require 'erubis/local-setting'
1523
1621
  #--end of require 'erubis'
1524
1622
  #--begin of require 'erubis/tiny'
1525
1623
  ##
1526
- ## $Rev: 35 $
1527
- ## $Release: 2.1.0 $
1528
- ## copyright(c) 2006 kuwata-lab all rights reserved.
1624
+ ## $Rev: 54 $
1625
+ ## $Release: 2.2.0 $
1626
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
1529
1627
  ##
1530
1628
 
1531
1629
  module Erubis
@@ -1549,44 +1647,47 @@ module Erubis
1549
1647
  EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m
1550
1648
 
1551
1649
  def convert(input)
1552
- src = "_buf = [];" # preamble
1650
+ src = "_buf = '';" # preamble
1553
1651
  pos = 0
1554
1652
  input.scan(EMBEDDED_PATTERN) do |indicator, code|
1555
1653
  match = Regexp.last_match
1556
- index = match.begin(0)
1557
- text = input[pos, index - pos]
1654
+ len = match.begin(0) - pos
1655
+ text = input[pos, len]
1558
1656
  pos = match.end(0)
1559
- src << " _buf << '" << escape_text(text) << "';"
1657
+ #src << " _buf << '" << escape_text(text) << "';"
1658
+ text.gsub!(/['\\]/, '\\\\\&')
1659
+ src << " _buf << '" << text << "';" unless text.empty?
1560
1660
  if !indicator # <% %>
1561
1661
  src << code << ";"
1562
- elsif indicator[0] == ?\# # <%# %>
1563
- n = code.count("\n")
1564
- add_stmt(src, "\n" * n)
1662
+ elsif indicator == '#' # <%# %>
1663
+ src << ("\n" * code.count("\n"))
1565
1664
  else # <%= %>
1566
1665
  src << " _buf << (" << code << ").to_s;"
1567
1666
  end
1568
1667
  end
1569
1668
  rest = $' || input
1570
- src << " _buf << '" << escape_text(rest) << "';"
1571
- src << "\n_buf.join\n" # postamble
1669
+ #src << " _buf << '" << escape_text(rest) << "';"
1670
+ rest.gsub!(/['\\]/, '\\\\\&')
1671
+ src << " _buf << '" << rest << "';" unless rest.empty?
1672
+ src << "\n_buf.to_s\n" # postamble
1572
1673
  return src
1573
1674
  end
1574
1675
 
1575
- def escape_text(text)
1576
- return text.gsub!(/['\\]/, '\\\\\&') || text
1577
- end
1676
+ #def escape_text(text)
1677
+ # return text.gsub!(/['\\]/, '\\\\\&') || text
1678
+ #end
1578
1679
 
1579
- def result(binding=TOPLEVEL_BINDING)
1580
- eval @src, binding
1680
+ def result(_binding=TOPLEVEL_BINDING)
1681
+ eval @src, _binding
1581
1682
  end
1582
1683
 
1583
- def evaluate(context=Object.new)
1584
- if context.is_a?(Hash)
1585
- obj = Object.new
1586
- context.each do |k, v| obj.instance_variable_set("@#{k}", v) end
1587
- context = obj
1684
+ def evaluate(_context=Object.new)
1685
+ if _context.is_a?(Hash)
1686
+ _obj = Object.new
1687
+ _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
1688
+ _context = _obj
1588
1689
  end
1589
- context.instance_eval @src
1690
+ _context.instance_eval @src
1590
1691
  end
1591
1692
 
1592
1693
  end
@@ -1605,56 +1706,58 @@ module Erubis
1605
1706
 
1606
1707
  attr_reader :src
1607
1708
 
1608
- EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|\$(!*)?\{(.*?)\}/
1709
+ EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m
1609
1710
 
1610
1711
  def convert(input)
1611
- src = "_buf = [];" # preamble
1712
+ src = "_buf = '';" # preamble
1612
1713
  pos = 0
1613
- input.scan(EMBEDDED_PATTERN) do |lspace, stmtcode, rspace, indicator, exprcode|
1714
+ input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr|
1614
1715
  match = Regexp.last_match
1615
- index = match.begin(0)
1616
- text = input[pos, index - pos]
1716
+ len = match.begin(0) - pos
1717
+ text = input[pos, len]
1617
1718
  pos = match.end(0)
1618
- if stmtcode # <?rb ... ?>
1619
- code = stmtcode
1620
- src << " _buf << '" << escape_text(text) << "';"
1719
+ #src << " _buf << '" << escape_text(text) << "';"
1720
+ text.gsub!(/['\\]/, '\\\\\&')
1721
+ src << " _buf << '" << text << "';" unless text.empty?
1722
+ if stmt # <?rb ... ?>
1621
1723
  if lspace && rspace
1622
- src << "#{lspace}#{code}#{rspace}"
1724
+ src << "#{lspace}#{stmt}#{rspace}"
1623
1725
  else
1624
- src << " _buf << '#{lspace}';" if lspace
1625
- src << code << ";"
1626
- src << " _buf << '#{rspace}';" if rspace
1726
+ src << " _buf << '" << lspace << "';" if lspace
1727
+ src << stmt << ";"
1728
+ src << " _buf << '" << rspace << "';" if rspace
1627
1729
  end
1628
1730
  else # ${...}, $!{...}
1629
- code = exprcode
1630
- if indicator.nil? || indicator.empty?
1631
- src << " _buf << #{@escape}(" << code << ");"
1731
+ if !indicator
1732
+ src << " _buf << " << @escape << "(" << expr << ");"
1632
1733
  elsif indicator == '!'
1633
- src << " _buf << (" << code << ").to_s;"
1734
+ src << " _buf << (" << expr << ").to_s;"
1634
1735
  end
1635
1736
  end
1636
1737
  end
1637
1738
  rest = $' || input
1638
- src << " _buf << '" << escape_text(rest) << "';"
1639
- src << "\n_buf.join\n" # postamble
1739
+ #src << " _buf << '" << escape_text(rest) << "';"
1740
+ rest.gsub!(/['\\]/, '\\\\\&')
1741
+ src << " _buf << '" << rest << "';" unless rest.empty?
1742
+ src << "\n_buf.to_s\n" # postamble
1640
1743
  return src
1641
1744
  end
1642
1745
 
1643
- def escape_text(text)
1644
- return text.gsub!(/['\\]/, '\\\\\&') || text
1645
- end
1746
+ #def escape_text(text)
1747
+ # return text.gsub!(/['\\]/, '\\\\\&') || text
1748
+ #end
1646
1749
 
1647
- def result(binding=TOPLEVEL_BINDING)
1648
- eval @src, binding
1750
+ def result(_binding=TOPLEVEL_BINDING)
1751
+ eval @src, _binding
1649
1752
  end
1650
1753
 
1651
- def evaluate(context=Object.new)
1652
- if context.is_a?(Hash)
1653
- obj = Object.new
1654
- context.each do |k, v| obj.instance_variable_set("@#{k}", v) end
1655
- context = obj
1754
+ def evaluate(_context=Object.new)
1755
+ if _context.is_a?(Hash)
1756
+ _obj = Object.new
1757
+ _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
1758
+ _context = _obj
1656
1759
  end
1657
- context.instance_eval @src
1760
+ _context.instance_eval @src
1658
1761
  end
1659
1762
 
1660
1763
  end
@@ -1665,8 +1768,8 @@ end
1665
1768
  #--begin of require 'erubis/engine/enhanced'
1666
1769
  ##
1667
1770
  ## $Rev: 27 $
1668
- ## $Release: 2.1.0 $
1669
- ## copyright(c) 2006 kuwata-lab all rights reserved.
1771
+ ## $Release: 2.2.0 $
1772
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
1670
1773
  ##
1671
1774
 
1672
1775
  #--already included require 'erubis/enhancer'
@@ -1774,8 +1877,8 @@ end
1774
1877
  #--begin of require 'erubis/engine/optimized'
1775
1878
  ##
1776
1879
  ## $Rev: 31 $
1777
- ## $Release: 2.1.0 $
1778
- ## copyright(c) 2006 kuwata-lab all rights reserved.
1880
+ ## $Release: 2.2.0 $
1881
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
1779
1882
  ##
1780
1883
 
1781
1884
 
@@ -1905,8 +2008,8 @@ end
1905
2008
  #--begin of require 'erubis/engine/ephp'
1906
2009
  ##
1907
2010
  ## $Rev: 31 $
1908
- ## $Release: 2.1.0 $
1909
- ## copyright(c) 2006 kuwata-lab all rights reserved.
2011
+ ## $Release: 2.2.0 $
2012
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
1910
2013
  ##
1911
2014
 
1912
2015
  #--already included require 'erubis/engine'
@@ -2007,8 +2110,8 @@ end
2007
2110
  #--begin of require 'erubis/engine/ec'
2008
2111
  ##
2009
2112
  ## $Rev: 33 $
2010
- ## $Release: 2.1.0 $
2011
- ## copyright(c) 2006 kuwata-lab all rights reserved.
2113
+ ## $Release: 2.2.0 $
2114
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
2012
2115
  ##
2013
2116
 
2014
2117
  #--already included require 'erubis/engine'
@@ -2127,8 +2230,8 @@ end
2127
2230
  #--begin of require 'erubis/engine/ejava'
2128
2231
  ##
2129
2232
  ## $Rev: 31 $
2130
- ## $Release: 2.1.0 $
2131
- ## copyright(c) 2006 kuwata-lab all rights reserved.
2233
+ ## $Release: 2.2.0 $
2234
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
2132
2235
  ##
2133
2236
 
2134
2237
  #--already included require 'erubis/engine'
@@ -2240,8 +2343,8 @@ end
2240
2343
  #--begin of require 'erubis/engine/escheme'
2241
2344
  ##
2242
2345
  ## $Rev: 33 $
2243
- ## $Release: 2.1.0 $
2244
- ## copyright(c) 2006 kuwata-lab all rights reserved.
2346
+ ## $Release: 2.2.0 $
2347
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
2245
2348
  ##
2246
2349
 
2247
2350
  #--already included require 'erubis/engine'
@@ -2357,8 +2460,8 @@ end
2357
2460
  #--begin of require 'erubis/engine/eperl'
2358
2461
  ##
2359
2462
  ## $Rev: 40 $
2360
- ## $Release: 2.1.0 $
2361
- ## copyright(c) 2006 kuwata-lab all rights reserved.
2463
+ ## $Release: 2.2.0 $
2464
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
2362
2465
  ##
2363
2466
 
2364
2467
  #--already included require 'erubis/engine'
@@ -2455,8 +2558,8 @@ end
2455
2558
  #--begin of require 'erubis/engine/ejavascript'
2456
2559
  ##
2457
2560
  ## $Rev: 31 $
2458
- ## $Release: 2.1.0 $
2459
- ## copyright(c) 2006 kuwata-lab all rights reserved.
2561
+ ## $Release: 2.2.0 $
2562
+ ## copyright(c) 2006-2007 kuwata-lab all rights reserved.
2460
2563
  ##
2461
2564
 
2462
2565
  #--already included require 'erubis/engine'
@@ -2601,22 +2704,24 @@ module Erubis
2601
2704
  end
2602
2705
 
2603
2706
  def initialize
2604
- @single_options = "hvxTtSbeB"
2605
- @arg_options = "pcrfKIlaE"
2707
+ @single_options = "hvxztSbeB"
2708
+ @arg_options = "pcrfKIlaEC"
2606
2709
  @option_names = {
2607
2710
  ?h => :help,
2608
2711
  ?v => :version,
2609
2712
  ?x => :source,
2610
- ?T => :notrim,
2713
+ ?z => :syntax,
2714
+ #?T => :notrim,
2611
2715
  ?t => :untabify,
2612
2716
  ?S => :intern,
2613
2717
  ?b => :bodyonly,
2614
2718
  ?B => :binding,
2615
2719
  ?p => :pattern,
2616
- ?c => :class,
2720
+ ?c => :context,
2721
+ ?C => :class,
2617
2722
  ?e => :escape,
2618
2723
  ?r => :requires,
2619
- ?f => :yamlfiles,
2724
+ ?f => :datafiles,
2620
2725
  ?K => :kanji,
2621
2726
  ?I => :includes,
2622
2727
  ?l => :lang,
@@ -2664,6 +2769,7 @@ module Erubis
2664
2769
 
2665
2770
  ## action
2666
2771
  action = opts.action
2772
+ action ||= 'syntax' if opts.syntax
2667
2773
  action ||= 'convert' if opts.source
2668
2774
 
2669
2775
  ## lang
@@ -2678,13 +2784,18 @@ module Erubis
2678
2784
  $KCODE = opts.kanji if opts.kanji
2679
2785
 
2680
2786
  ## read context values from yaml file
2681
- yamlfiles = opts.yamlfiles
2682
- context = load_yamlfiles(yamlfiles, opts)
2787
+ datafiles = opts.datafiles
2788
+ context = load_datafiles(datafiles, opts)
2789
+
2790
+ ## parse context data
2791
+ if opts.context
2792
+ context = parse_context_data(opts.context, opts)
2793
+ end
2683
2794
 
2684
2795
  ## properties for engine
2685
2796
  properties[:escape] = true if opts.escape && !properties.key?(:escape)
2686
2797
  properties[:pattern] = opts.pattern if opts.pattern
2687
- properties[:trim] = false if opts.notrim
2798
+ #properties[:trim] = false if opts.notrim
2688
2799
  properties[:preamble] = properties[:postamble] = false if opts.bodyonly
2689
2800
  properties[:pi] = nil if properties[:pi] == true
2690
2801
 
@@ -2699,32 +2810,39 @@ module Erubis
2699
2810
 
2700
2811
  ## convert and execute
2701
2812
  val = nil
2813
+ msg = "Syntax OK\n"
2702
2814
  if filenames && !filenames.empty?
2703
2815
  filenames.each do |filename|
2704
2816
  test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
2705
2817
  engine.filename = filename
2706
2818
  engine.convert!(File.read(filename))
2707
- print val if val = do_action(action, engine, context, opts)
2819
+ val = do_action(action, engine, context, filename, opts)
2820
+ msg = nil if val
2708
2821
  end
2709
2822
  else
2710
2823
  engine.filename = '(stdin)'
2711
2824
  engine.convert!($stdin.read())
2712
- print val if val = do_action(action, engine, context, opts)
2825
+ val = do_action(action, engine, context, filename, opts)
2826
+ msg = nil if val
2713
2827
  end
2828
+ print msg if action == 'syntax' && msg
2714
2829
 
2715
2830
  end
2716
2831
 
2717
2832
  private
2718
2833
 
2719
- def do_action(action, engine, context, opts)
2834
+ def do_action(action, engine, context, filename, opts)
2720
2835
  case action
2721
2836
  when 'convert'
2722
2837
  s = engine.src
2723
2838
  when nil, 'exec', 'execute'
2724
- s = opts.binding ? engine.result(context) : engine.evaluate(context)
2839
+ s = opts.binding ? engine.result(context.to_hash) : engine.evaluate(context)
2840
+ when 'syntax'
2841
+ s = check_syntax(filename, engine.src)
2725
2842
  else
2726
2843
  raise "*** internal error"
2727
2844
  end
2845
+ print s if s
2728
2846
  return s
2729
2847
  end
2730
2848
 
@@ -2735,8 +2853,8 @@ erubis - embedded program converter for multi-language
2735
2853
  Usage: #{command} [..options..] [file ...]
2736
2854
  -h, --help : help
2737
2855
  -v : version
2738
- -x : converted code
2739
- -T : don't trim spaces around '<% %>'
2856
+ -x : show converted code
2857
+ -z : syntax checking
2740
2858
  -b : body only (no preamble nor postamble)
2741
2859
  -e : escape (equal to '--E Escape')
2742
2860
  -p pattern : embedded pattern (default '<% %>')
@@ -2744,7 +2862,8 @@ Usage: #{command} [..options..] [file ...]
2744
2862
  -E e1,e2,... : enhancer names (Escape, PercentLine, BiPattern, ...)
2745
2863
  -I path : library include path
2746
2864
  -K kanji : kanji code (euc/sjis/utf8) (default none)
2747
- -f file.yaml : YAML file for context values (read stdin if filename is '-')
2865
+ -c context : context data string (yaml inline style or ruby code)
2866
+ -f datafile : context data file ('*.yaml', '*.yml', or '*.rb')
2748
2867
  -t : expand tab character in YAML file
2749
2868
  -S : convert mapping key from string to symbol in YAML file
2750
2869
  -B : invoke 'result(binding)' instead of 'evaluate(context)'
@@ -2752,6 +2871,7 @@ Usage: #{command} [..options..] [file ...]
2752
2871
 
2753
2872
  END
2754
2873
  #'
2874
+ # -T : don't trim spaces around '<% %>'
2755
2875
  # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
2756
2876
  # -r library : require library
2757
2877
  # -a : action (convert/execute)
@@ -2806,8 +2926,7 @@ END
2806
2926
  end
2807
2927
 
2808
2928
  def version
2809
- release = ('$Release: 2.1.0 $' =~ /([.\d]+)/) && $1
2810
- return release
2929
+ return Erubis::VERSION
2811
2930
  end
2812
2931
 
2813
2932
  def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
@@ -2914,27 +3033,51 @@ END
2914
3033
  return enhancers
2915
3034
  end
2916
3035
 
2917
- def load_yamlfiles(yamlfiles, opts)
2918
- hash = {}
2919
- return hash unless yamlfiles
2920
- yamlfiles.split(/,/).each do |yamlfile|
2921
- if yamlfile == '-'
2922
- str = $stdin.read()
3036
+ def load_datafiles(filenames, opts)
3037
+ context = Erubis::Context.new
3038
+ return hash unless filenames
3039
+ filenames.split(/,/).each do |filename|
3040
+ filename.strip!
3041
+ test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
3042
+ if filename =~ /\.ya?ml$/
3043
+ if opts.untabify
3044
+ ydoc = YAML.load(untabify(File.read(filename)))
3045
+ else
3046
+ ydoc = YAML.load_file(filename)
3047
+ end
3048
+ ydoc.is_a?(Hash) or raise CommandOptionError.new("#{filename}: root object is not a mapping.")
3049
+ intern_hash_keys(ydoc) if opts.intern
3050
+ context.update(ydoc)
3051
+ elsif filename =~ /\.rb$/
3052
+ str = File.read(filename)
3053
+ context2 = Erubis::Context.new
3054
+ _instance_eval(context2, str)
3055
+ context.update(context2)
2923
3056
  else
2924
- test(?f, yamlfile) or raise CommandOptionError.new("#{yamlfile}: file not found.")
2925
- str = File.read(yamlfile)
3057
+ CommandOptionError.new("#{filename}: '*.yaml', '*.yml', or '*.rb' required.")
2926
3058
  end
2927
- str = yamlfile == '-' ? $stdin.read() : File.read(yamlfile)
2928
- str = untabify(str) if opts.untabify
2929
- ydoc = YAML.load(str)
3059
+ end
3060
+ return context
3061
+ end
3062
+
3063
+ def _instance_eval(_context, _str)
3064
+ _context.instance_eval(_str)
3065
+ end
3066
+
3067
+ def parse_context_data(context_str, opts)
3068
+ if context_str[0] == ?{
3069
+ require 'yaml'
3070
+ ydoc = YAML.load(context_str)
2930
3071
  unless ydoc.is_a?(Hash)
2931
- raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
3072
+ raise CommandOptionError.new("-c: root object is not a mapping.")
2932
3073
  end
2933
3074
  intern_hash_keys(ydoc) if opts.intern
2934
- hash.update(ydoc)
3075
+ return ydoc
3076
+ else
3077
+ context = Erubis::Context.new
3078
+ context.instance_eval(context_str, '-c')
3079
+ return context
2935
3080
  end
2936
- context = hash
2937
- return context
2938
3081
  end
2939
3082
 
2940
3083
  def intern_hash_keys(obj, done={})
@@ -2956,6 +3099,21 @@ END
2956
3099
  end
2957
3100
  end
2958
3101
 
3102
+ def check_syntax(filename, src)
3103
+ require 'open3'
3104
+ stdin, stdout, stderr = Open3.popen3('ruby -wc')
3105
+ stdin.write(src)
3106
+ stdin.close
3107
+ result = stdout.read()
3108
+ stdout.close()
3109
+ errmsg = stderr.read()
3110
+ stderr.close()
3111
+ return nil unless errmsg && !errmsg.empty?
3112
+ errmsg =~ /\A-:(\d+): /
3113
+ linenum, message = $1, $'
3114
+ return "#{filename}:#{linenum}: #{message}"
3115
+ end
3116
+
2959
3117
  end
2960
3118
 
2961
3119
  end