summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormakoto kuwata <kwa@kuwata-lab.com>2006-05-03 10:10:13 +0000
committermakoto kuwata <kwa@kuwata-lab.com>2006-05-03 10:10:13 +0000
commit675a3fd420e4e72b2a9846eb93269ae24c554850 (patch)
tree5a1cc1ab97030619d836be24bcbab6f21f25559e
parent118f9b3afb9cc26fd64fae6924c8b3b4742eb96f (diff)
downloaderubis-675a3fd420e4e72b2a9846eb93269ae24c554850.tar.gz
- [change] 'simplest.rb' is renamed to 'tiny.rb'
- [enhance] add Context class - [enahnce] Engine#enhacne() now support Context object - [enhance] new command-line option '-X' (convert to context obj) added
-rw-r--r--ChangeLog.txt6
-rw-r--r--benchmark/erubybench-lib.rb4
-rw-r--r--benchmark/erubybench.rb12
-rw-r--r--doc/Rookbook.yaml4
-rw-r--r--doc/users-guide.html183
-rw-r--r--doc/users-guide.txt166
-rw-r--r--lib/erubis.rb2
-rw-r--r--lib/erubis/engine.rb49
-rw-r--r--lib/erubis/main.rb135
-rw-r--r--lib/erubis/tiny.rb (renamed from lib/erubis/simplest.rb)14
-rw-r--r--test/test-bin.rb33
-rw-r--r--test/test-erubis.rb31
12 files changed, 448 insertions, 191 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 35beca5..4683d23 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -2,6 +2,12 @@
.?lastupdate: $Date$
.?version: $Rev$
+.: Rev.16
+ .- [change] 'simplest.rb' is renamed to 'tiny.rb'
+ .- [enhance] add Context class
+ .- [enahnce] Engine#enhacne() now support Context object
+ .- [enhance] new command-line option '-X' (convert to context obj) added
+
.: Rev.15 (2006-05-02)
.- [refactor] Engine#compile() refactored
.- [refactor] XxxxXmlEruby classes are removed
diff --git a/benchmark/erubybench-lib.rb b/benchmark/erubybench-lib.rb
index 8d2ea73..32ca299 100644
--- a/benchmark/erubybench-lib.rb
+++ b/benchmark/erubybench-lib.rb
@@ -18,7 +18,7 @@ module Erubis
##
## use $stdout
##
- class SimplestStdoutEruby
+ class TinyStdoutEruby
def initialize(input)
@src = compile(input)
@@ -60,7 +60,7 @@ module Erubis
##
## use print statement
##
- class SimplestPrintEruby
+ class TinyPrintEruby
def initialize(input)
@src = compile(input)
diff --git a/benchmark/erubybench.rb b/benchmark/erubybench.rb
index 0073375..2eaa166 100644
--- a/benchmark/erubybench.rb
+++ b/benchmark/erubybench.rb
@@ -163,18 +163,18 @@ testdefs_str = <<END
return: str
skip: no
-- name: ErubisSimplest
- class: Erubis::SimplestEruby
+- name: ErubisTiny
+ class: Erubis::TinyEruby
return: yes
skip: no
-- name: ErubisSimplestStdout
- class: Erubis::SimplestStdoutEruby
+- name: ErubisTinyStdout
+ class: Erubis::TinyStdoutEruby
return: null
skip: no
-- name: ErubisSimplestPrint
- class: Erubis::SimplestPrintEruby
+- name: ErubisTinyPrint
+ class: Erubis::TinyPrintEruby
return: null
skip: no
diff --git a/doc/Rookbook.yaml b/doc/Rookbook.yaml
index a051c23..4cb0434 100644
--- a/doc/Rookbook.yaml
+++ b/doc/Rookbook.yaml
@@ -21,9 +21,9 @@ recipes:
rm_rf "guide.d"
mkdir_p "guide.d"
cmd "retrieve -d guide.d #{@ingred}"
- cmd "kwaser -t $(tagfile) -T #{@ingred} > #{@byprods[0]}"
+ cmd "kwaser -t $(tagfile) -T #{@ingred} > #{@byprod}"
cmd "kwaser -t $(tagfile) #{@ingred} > #{@product}"
- rm "#{@byprods[0]}"
+ rm "#{@byprod}"
diff --git a/doc/users-guide.html b/doc/users-guide.html
index 864d7c0..d707c7f 100644
--- a/doc/users-guide.html
+++ b/doc/users-guide.html
@@ -37,7 +37,7 @@ It has the following features.
</li>
<li>Print statement available
</li>
-<li>Easy to expand in subclass
+<li>Easy to extend in subclass
</li>
</ul>
<p>Erubis is implemented in pure Ruby. It requires Ruby 1.8 or higher.
@@ -65,6 +65,8 @@ It has the following features.
</li>
<li><a href="#tut-context">Context Object</a>
</li>
+ <li><a href="#tut-datafile">Context Data File</a>
+ </li>
<li><a href="#Preamble and Postamble">Preamble and Postamble</a>
</li>
</ul>
@@ -367,6 +369,14 @@ $ cat stderr.log
This is available in any language.
</p>
<pre class="terminal">$ erubis -l ruby <b>-e Escape</b> example3.eruby
+_out = []; for item in list
+; _out &lt;&lt; ' - '; _out &lt;&lt; Erubis::XmlHelper.escape_xml( item ); _out &lt;&lt; '
+'; _out &lt;&lt; ' - '; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; '
+'; _out &lt;&lt; ' - '; $stderr.puts("*** debug: item=#{(item).inspect}"); _out &lt;&lt; '
+'; _out &lt;&lt; '
+'; end
+;
+_out.join
</pre>
<p>Escaping function (default 'Erubis::XmlHelper.escape_xml()') can be changed by command-line property '--escape=xxx' or by overriding Erubis::Eruby#escaped_expr() in subclass.
</p>
@@ -445,9 +455,10 @@ For example, '<code>&lt;(!--)?% %(--)?&gt;</code>' will not work while '<code>&l
<h3 class="section2">Context Object</h3>
<p>Context object is a set of data which are used in eRuby script.
Using context object makes clear which data to be used.
+In Erubis, Hash object and Erubis::Context object are available as context object.
</p>
-<p>In Erubis, Hash object is used as context object.
-Hash key means variable name and it can be string or symbol.
+<p>When using Hash as context object,
+hash key means variable name and it should be string or symbol.
</p>
<a name="example5.eruby"></a>
<div class="program_caption">
@@ -484,11 +495,69 @@ output</div>
&lt;li&gt;ccc&lt;/li&gt;
&lt;/ul&gt;
</pre>
-<p>It is very useful to import YAML document data into context object.
+<p>When using Erubis::Context object, context data is accessible via instance variables in eRuby template.
</p>
-<a name="example6.yaml"></a>
+<a name="example6.eruby"></a>
+<div class="program_caption">
+example6.eruby</div>
+<pre class="program">&lt;span&gt;&lt;%= <b>@val</b> %&gt;&lt;/span&gt;
+&lt;ul&gt;
+ &lt;% for item in <b>@list</b> %&gt;
+ &lt;li&gt;&lt;%= item %&gt;&lt;/li&gt;
+ &lt;% end %&gt;
+&lt;/ul&gt;
+</pre>
+<a name="example6.rb"></a>
<div class="program_caption">
-example6.yaml</div>
+example6.rb</div>
+<pre class="program">require 'erubis'
+input = File.read('example6.eruby')
+eruby = Erubis::Eruby.new(input) # create Eruby object
+
+## create context object
+## (key means var name, which may be string or symbol.)
+<b>context = Erubis::Context.new</b>
+<b>context[:val] = 'Erubis Example'</b>
+<b>context['list'] = ['aaa', 'bbb', 'ccc']</b>
+
+puts <b>eruby.evaluate(context)</b> # get result
+</pre>
+<div class="terminal_caption">
+output</div>
+<pre class="terminal">$ ruby example6.rb
+&lt;span&gt;Erubis Example&lt;/span&gt;
+&lt;ul&gt;
+ &lt;li&gt;aaa&lt;/li&gt;
+ &lt;li&gt;bbb&lt;/li&gt;
+ &lt;li&gt;ccc&lt;/li&gt;
+&lt;/ul&gt;
+</pre>
+<p><code>eruby.evaluate(context)</code> is almost equivalent to <code>context.instance_eval(eruby.src)</code>.
+In fact, eruby.evaluate() can take any object.
+</p>
+<pre class="program">class MyData
+ def initialize(val, list)
+ @val = val
+ @list = list
+ end
+end
+
+<b>mydata = MyData.new</b>('Erubis Example', ['aaa', 'bbb', 'ccc'])
+
+require 'erubis'
+eruby = Erubis::Eruby.new(File.read('example6.eruby'))
+puts eruby.evaluate(<b>mydata</b>)
+</pre>
+<br>
+
+
+<a name="tut-datafile"></a>
+<h3 class="section2">Context Data File</h3>
+<p>It is very useful to import YAML document data into Hash context object.
+</p>
+<a name="example7.yaml"></a>
+<div class="program_caption">
+example7.yaml</div>
<pre class="program">title: Users List
users:
- name: foo
@@ -498,9 +567,9 @@ users:
- name: baz
mail: baz@mail.org
</pre>
-<a name="example6.eruby"></a>
+<a name="example7.eruby"></a>
<div class="program_caption">
-example6.eruby</div>
+example7.eruby</div>
<pre class="program">&lt;h1&gt;&lt;%= title %&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;% for user in users %&gt;
@@ -510,22 +579,41 @@ example6.eruby</div>
&lt;% end %&gt;
&lt;/ul&gt;
</pre>
-<a name="example6.rb"></a>
+<a name="example7.rb"></a>
<div class="program_caption">
-example6.rb</div>
+example7.rb</div>
<pre class="program">require 'erubis'
-input = File.read('example6.eruby')
+input = File.read('example7.eruby')
eruby = Erubis::Eruby.new(input) # create Eruby object
## load YAML document as context object
<b>require 'yaml'</b>
-<b>context = YAML.load_file('example6.yaml')</b>
+<b>context = YAML.load_file('example7.yaml')</b>
puts <b>eruby.evaluate(context)</b> # get result
</pre>
<div class="terminal_caption">
output</div>
-<pre class="terminal">$ ruby example6.rb
+<pre class="terminal">$ ruby example7.rb
+&lt;h1&gt;Users List&lt;/h1&gt;
+&lt;ul&gt;
+ &lt;li&gt;
+ &lt;a href="mailto:foo@mail.com"&gt;foo&lt;/a&gt;
+ &lt;/li&gt;
+ &lt;li&gt;
+ &lt;a href="mailto:bar@mail.net"&gt;bar&lt;/a&gt;
+ &lt;/li&gt;
+ &lt;li&gt;
+ &lt;a href="mailto:baz@mail.org"&gt;baz&lt;/a&gt;
+ &lt;/li&gt;
+&lt;/ul&gt;
+</pre>
+<p>It is able to specify YAML data file with the command-line option '-f'.
+You don't have to write ruby script such as 'example7.rb'.
+</p>
+<div class="terminal_caption">
+example of command-line option '-f'</div>
+<pre class="terminal">$ erubis <b>-f example7.yaml</b> example7.eruby
&lt;h1&gt;Users List&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
@@ -539,6 +627,9 @@ output</div>
&lt;/li&gt;
&lt;/ul&gt;
</pre>
+<p>Command-line option '-S' converts keys of mapping in YAML data file from string into symbol.
+Command-line option '-X' use Erubis::Context as context object.
+</p>
<br>
@@ -549,18 +640,18 @@ and the last line ('_out.join') is called postamble.
</p>
<p>You can specify Eruby not to print preamble nor postamble with option :preamble and :postamble.
</p>
-<a name="example7.eruby"></a>
+<a name="example8.eruby"></a>
<div class="program_caption">
-example7.eruby</div>
+example8.eruby</div>
<pre class="program">&lt;% for item in list %&gt;
&lt;b&gt;&lt;%= item %&gt;&lt;/b&gt;
&lt;% end %&gt;
</pre>
-<a name="example7.rb"></a>
+<a name="example8.rb"></a>
<div class="program_caption">
-example7.rb</div>
+example8.rb</div>
<pre class="program">require 'erubis'
-input = File.read('example7.eruby')
+input = File.read('example8.eruby')
eruby1 = Erubis::Eruby.new(input)
eruby2 = Erubis::Eruby.new(input, <b>:preamble=&gt;false, :postamble=&gt;false</b>)
@@ -570,7 +661,7 @@ puts eruby2.src # don't print preamble and postamble
</pre>
<div class="terminal_caption">
output</div>
-<pre class="terminal">$ ruby example7.rb
+<pre class="terminal">$ ruby example8.rb
_out = []; for item in list
; _out &lt;&lt; ' &lt;b&gt;'; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; '&lt;/b&gt;
'; end
@@ -1564,35 +1655,35 @@ Here is an example result of benchmark.
</p>
<div class="output_caption">
Env: Linux FedoraCore4, Celeron 667MHz, Mem512MB, Ruby1.8.4</div>
-<pre class="output"> user system total real
-ERuby 138.280000 1.900000 140.180000 (141.470426)
-ERB 402.220000 3.190000 405.410000 (408.886894)
-Erubis::Eruby 147.080000 2.400000 149.480000 (150.752255)
-Erubis::StringBufferEruby 186.130000 2.600000 188.730000 (190.374098)
-Erubis::SimplifiedEruby 130.100000 2.210000 132.310000 (133.426010)
-Erubis::StdoutEruby 106.010000 2.130000 108.140000 (108.999193)
-Erubis::StdoutSimplifiedEruby 97.130000 2.180000 99.310000 (100.104433)
-Erubis::PrintOutEruby 109.900000 2.090000 111.990000 (112.854442)
-Erubis::PrintOutSimplifiedEruby 93.120000 2.140000 95.260000 ( 96.002970)
-Erubis::SimplestEruby 118.740000 2.360000 121.100000 (122.141380)
-Erubis::SimplestStdoutEruby 86.140000 1.840000 87.980000 ( 88.679196)
-Erubis::SimplestPrintEruby 86.540000 1.970000 88.510000 ( 89.208078)
+<pre class="output"> user system total real
+ERuby 138.280000 1.900000 140.180000 (141.470426)
+ERB 402.220000 3.190000 405.410000 (408.886894)
+Erubis::Eruby 147.080000 2.400000 149.480000 (150.752255)
+Erubis::StringBufferEruby 186.130000 2.600000 188.730000 (190.374098)
+Erubis::SimplifiedEruby 130.100000 2.210000 132.310000 (133.426010)
+Erubis::StdoutEruby 106.010000 2.130000 108.140000 (108.999193)
+Erubis::StdoutSimplifiedEruby 97.130000 2.180000 99.310000 (100.104433)
+Erubis::PrintOutEruby 109.900000 2.090000 111.990000 (112.854442)
+Erubis::PrintOutSimplifiedEruby 93.120000 2.140000 95.260000 ( 96.002970)
+Erubis::TinyEruby 118.740000 2.360000 121.100000 (122.141380)
+Erubis::TinyStdoutEruby 86.140000 1.840000 87.980000 ( 88.679196)
+Erubis::TinyPrintEruby 86.540000 1.970000 88.510000 ( 89.208078)
</pre>
<div class="output_caption">
Env: MacOS X 10.4, PowerPC 1.42GHz, Mem1.5GB, Ruby1.8.4</div>
-<pre class="output"> user system total real
-ERuby 55.040000 2.120000 57.160000 ( 89.311397)
-ERB 103.960000 3.480000 107.440000 (159.231792)
-Erubis::Eruby 36.130000 1.570000 37.700000 ( 52.188574)
-Erubis::StringBufferEruby 47.270000 1.980000 49.250000 ( 73.867537)
-Erubis::SimplifiedEruby 34.310000 1.600000 35.910000 ( 51.762841)
-Erubis::StdoutEruby 26.240000 1.490000 27.730000 ( 41.840430)
-Erubis::StdoutSimplifiedEruby 25.380000 1.340000 26.720000 ( 37.231918)
-Erubis::PrintOutEruby 26.850000 1.260000 28.110000 ( 38.378227)
-Erubis::PrintOutSimplifiedEruby 24.160000 1.280000 25.440000 ( 40.048199)
-Erubis::SimplestEruby 31.690000 1.590000 33.280000 ( 49.862091)
-Erubis::SimplestStdoutEruby 22.550000 1.230000 23.780000 ( 33.316978)
-Erubis::SimplestPrintEruby 22.340000 1.150000 23.490000 ( 33.577150)
+<pre class="output"> user system total real
+ERuby 55.040000 2.120000 57.160000 ( 89.311397)
+ERB 103.960000 3.480000 107.440000 (159.231792)
+Erubis::Eruby 36.130000 1.570000 37.700000 ( 52.188574)
+Erubis::StringBufferEruby 47.270000 1.980000 49.250000 ( 73.867537)
+Erubis::SimplifiedEruby 34.310000 1.600000 35.910000 ( 51.762841)
+Erubis::StdoutEruby 26.240000 1.490000 27.730000 ( 41.840430)
+Erubis::StdoutSimplifiedEruby 25.380000 1.340000 26.720000 ( 37.231918)
+Erubis::PrintOutEruby 26.850000 1.260000 28.110000 ( 38.378227)
+Erubis::PrintOutSimplifiedEruby 24.160000 1.280000 25.440000 ( 40.048199)
+Erubis::TinyEruby 31.690000 1.590000 33.280000 ( 49.862091)
+Erubis::TinyStdoutEruby 22.550000 1.230000 23.780000 ( 33.316978)
+Erubis::TinyPrintEruby 22.340000 1.150000 23.490000 ( 33.577150)
</pre>
<p>This shows that:
</p>
@@ -1607,7 +1698,7 @@ Erubis::SimplestPrintEruby 22.340000 1.150000 23.490000 ( 33.5771
</li>
<li>Using print statement or $stdout is faster than array buffer and string buffer.
</li>
-<li>Erubis::SimplestEruby (at 'erubis/simples.rb') and it's subclasses are the fastest in all eRuby implementation.
+<li>Erubis::TinyEruby (at 'erubis/tiny.rb') and it's subclasses are the fastest in all eRuby implementation.
</li>
</ul>
<br>
diff --git a/doc/users-guide.txt b/doc/users-guide.txt
index 6666913..b6453bb 100644
--- a/doc/users-guide.txt
+++ b/doc/users-guide.txt
@@ -16,7 +16,7 @@ It has the following features.
.* Support multi-language (Ruby/PHP/C/Java/Scheme/Perl/Javascript)
.* Context object available and easy to combine eRuby template with YAML datafile
.* Print statement available
-.* Easy to expand in subclass
+.* Easy to extend in subclass
Erubis is implemented in pure Ruby. It requires Ruby 1.8 or higher.
@@ -246,7 +246,7 @@ This is available in any language.
.====================
$ erubis -l ruby {{*-e Escape*}} example3.eruby
-.<<<:! erubis -e Escape -l ruby example3.eruby
+.<<<:! (cd guide.d; erubis -e Escape -l ruby example3.eruby)
.====================
Escaping function (default 'Erubis::XmlHelper.escape_xml()') can be changed by command-line property '--escape=xxx' or by overriding Erubis::Eruby#escaped_expr() in subclass.
@@ -311,9 +311,10 @@ For example, '{{,<(!--)?% %(--)?>,}}' will not work while '{{,<(?:!--)?% %(?:--)
Context object is a set of data which are used in eRuby script.
Using context object makes clear which data to be used.
+In Erubis, Hash object and Erubis::Context object are available as context object.
-In Erubis, Hash object is used as context object.
-Hash key means variable name and it can be string or symbol.
+When using Hash as context object,
+hash key means variable name and it should be string or symbol.
.? example5.eruby
.-------------------- example5.eruby
@@ -346,10 +347,65 @@ $ ruby example5.rb
.<<<:! (cd guide.d; ruby example5.rb)
.====================
-It is very useful to import YAML document data into context object.
+When using Erubis::Context object, context data is accessible via instance variables in eRuby template.
-.? example6.yaml
-.-------------------- example6.yaml
+.? example6.eruby
+.-------------------- example6.eruby
+<span><%= {{*@val*}} %></span>
+<ul>
+ <% for item in {{*@list*}} %>
+ <li><%= item %></li>
+ <% end %>
+</ul>
+.--------------------
+
+.? example6.rb
+.-------------------- example6.rb
+require 'erubis'
+input = File.read('example6.eruby')
+eruby = Erubis::Eruby.new(input) # create Eruby object
+
+## create context object
+## (key means var name, which may be string or symbol.)
+{{*context = Erubis::Context.new*}}
+{{*context[:val] = 'Erubis Example'*}}
+{{*context['list'] = ['aaa', 'bbb', 'ccc']*}}
+
+puts {{*eruby.evaluate(context)*}} # get result
+.--------------------
+
+.? output
+.====================
+$ ruby example6.rb
+.<<<:! (cd guide.d; ruby example6.rb)
+.====================
+
+{{,eruby.evaluate(context),}} is almost equivalent to {{,context.instance_eval(eruby.src),}}.
+In fact, eruby.evaluate() can take any object.
+
+.--------------------
+class MyData
+ def initialize(val, list)
+ @val = val
+ @list = list
+ end
+end
+
+{{*mydata = MyData.new*}}('Erubis Example', ['aaa', 'bbb', 'ccc'])
+
+require 'erubis'
+eruby = Erubis::Eruby.new(File.read('example6.eruby'))
+puts eruby.evaluate({{*mydata*}})
+.--------------------
+
+
+
+.$$ Context Data File | tut-datafile
+
+It is very useful to import YAML document data into Hash context object.
+
+.? example7.yaml
+.-------------------- example7.yaml
title: Users List
users:
- name: foo
@@ -360,8 +416,8 @@ users:
mail: baz@mail.org
.--------------------
-.? example6.eruby
-.-------------------- example6.eruby
+.? example7.eruby
+.-------------------- example7.eruby
<h1><%= title %></h1>
<ul>
<% for user in users %>
@@ -372,25 +428,37 @@ users:
</ul>
.--------------------
-.? example6.rb
-.-------------------- example6.rb
+.? example7.rb
+.-------------------- example7.rb
require 'erubis'
-input = File.read('example6.eruby')
+input = File.read('example7.eruby')
eruby = Erubis::Eruby.new(input) # create Eruby object
## load YAML document as context object
{{*require 'yaml'*}}
-{{*context = YAML.load_file('example6.yaml')*}}
+{{*context = YAML.load_file('example7.yaml')*}}
puts {{*eruby.evaluate(context)*}} # get result
.--------------------
.? output
.====================
-$ ruby example6.rb
-.<<<:! (cd guide.d; ruby example6.rb)
+$ ruby example7.rb
+.<<<:! (cd guide.d; ruby example7.rb)
+.====================
+
+It is able to specify YAML data file with the command-line option '-f'.
+You don't have to write ruby script such as 'example7.rb'.
+
+.? example of command-line option '-f'
+.====================
+$ erubis {{*-f example7.yaml*}} example7.eruby
+.<<<:! (cd guide.d; erubis -f example7.yaml example7.eruby)
.====================
+Command-line option '-S' converts keys of mapping in YAML data file from string into symbol.
+Command-line option '-X' use Erubis::Context as context object.
+
.$$ Preamble and Postamble
@@ -400,17 +468,17 @@ and the last line ('_out.join') is called postamble.
You can specify Eruby not to print preamble nor postamble with option :preamble and :postamble.
-.? example7.eruby
-.-------------------- example7.eruby
+.? example8.eruby
+.-------------------- example8.eruby
<% for item in list %>
<b><%= item %></b>
<% end %>
.--------------------
-.? example7.rb
-.-------------------- example7.rb
+.? example8.rb
+.-------------------- example8.rb
require 'erubis'
-input = File.read('example7.eruby')
+input = File.read('example8.eruby')
eruby1 = Erubis::Eruby.new(input)
eruby2 = Erubis::Eruby.new(input, {{*:preamble=>false, :postamble=>false*}})
@@ -421,8 +489,8 @@ puts eruby2.src # don't print preamble and postamble
.? output
.====================
-$ ruby example7.rb
-.<<<:! (cd guide.d; ruby example7.rb)
+$ ruby example8.rb
+.<<<:! (cd guide.d; ruby example8.rb)
.====================
The command-line option '-b' specify both :preamble and :postamble to false.
@@ -1130,36 +1198,36 @@ Here is an example result of benchmark.
.? Env: Linux FedoraCore4, Celeron 667MHz, Mem512MB, Ruby1.8.4
.____________________
- user system total real
-ERuby 138.280000 1.900000 140.180000 (141.470426)
-ERB 402.220000 3.190000 405.410000 (408.886894)
-Erubis::Eruby 147.080000 2.400000 149.480000 (150.752255)
-Erubis::StringBufferEruby 186.130000 2.600000 188.730000 (190.374098)
-Erubis::SimplifiedEruby 130.100000 2.210000 132.310000 (133.426010)
-Erubis::StdoutEruby 106.010000 2.130000 108.140000 (108.999193)
-Erubis::StdoutSimplifiedEruby 97.130000 2.180000 99.310000 (100.104433)
-Erubis::PrintOutEruby 109.900000 2.090000 111.990000 (112.854442)
-Erubis::PrintOutSimplifiedEruby 93.120000 2.140000 95.260000 ( 96.002970)
-Erubis::SimplestEruby 118.740000 2.360000 121.100000 (122.141380)
-Erubis::SimplestStdoutEruby 86.140000 1.840000 87.980000 ( 88.679196)
-Erubis::SimplestPrintEruby 86.540000 1.970000 88.510000 ( 89.208078)
+ user system total real
+ERuby 138.280000 1.900000 140.180000 (141.470426)
+ERB 402.220000 3.190000 405.410000 (408.886894)
+Erubis::Eruby 147.080000 2.400000 149.480000 (150.752255)
+Erubis::StringBufferEruby 186.130000 2.600000 188.730000 (190.374098)
+Erubis::SimplifiedEruby 130.100000 2.210000 132.310000 (133.426010)
+Erubis::StdoutEruby 106.010000 2.130000 108.140000 (108.999193)
+Erubis::StdoutSimplifiedEruby 97.130000 2.180000 99.310000 (100.104433)
+Erubis::PrintOutEruby 109.900000 2.090000 111.990000 (112.854442)
+Erubis::PrintOutSimplifiedEruby 93.120000 2.140000 95.260000 ( 96.002970)
+Erubis::TinyEruby 118.740000 2.360000 121.100000 (122.141380)
+Erubis::TinyStdoutEruby 86.140000 1.840000 87.980000 ( 88.679196)
+Erubis::TinyPrintEruby 86.540000 1.970000 88.510000 ( 89.208078)
.____________________
.? Env: MacOS X 10.4, PowerPC 1.42GHz, Mem1.5GB, Ruby1.8.4
.____________________
- user system total real
-ERuby 55.040000 2.120000 57.160000 ( 89.311397)
-ERB 103.960000 3.480000 107.440000 (159.231792)
-Erubis::Eruby 36.130000 1.570000 37.700000 ( 52.188574)
-Erubis::StringBufferEruby 47.270000 1.980000 49.250000 ( 73.867537)
-Erubis::SimplifiedEruby 34.310000 1.600000 35.910000 ( 51.762841)
-Erubis::StdoutEruby 26.240000 1.490000 27.730000 ( 41.840430)
-Erubis::StdoutSimplifiedEruby 25.380000 1.340000 26.720000 ( 37.231918)
-Erubis::PrintOutEruby 26.850000 1.260000 28.110000 ( 38.378227)
-Erubis::PrintOutSimplifiedEruby 24.160000 1.280000 25.440000 ( 40.048199)
-Erubis::SimplestEruby 31.690000 1.590000 33.280000 ( 49.862091)
-Erubis::SimplestStdoutEruby 22.550000 1.230000 23.780000 ( 33.316978)
-Erubis::SimplestPrintEruby 22.340000 1.150000 23.490000 ( 33.577150)
+ user system total real
+ERuby 55.040000 2.120000 57.160000 ( 89.311397)
+ERB 103.960000 3.480000 107.440000 (159.231792)
+Erubis::Eruby 36.130000 1.570000 37.700000 ( 52.188574)
+Erubis::StringBufferEruby 47.270000 1.980000 49.250000 ( 73.867537)
+Erubis::SimplifiedEruby 34.310000 1.600000 35.910000 ( 51.762841)
+Erubis::StdoutEruby 26.240000 1.490000 27.730000 ( 41.840430)
+Erubis::StdoutSimplifiedEruby 25.380000 1.340000 26.720000 ( 37.231918)
+Erubis::PrintOutEruby 26.850000 1.260000 28.110000 ( 38.378227)
+Erubis::PrintOutSimplifiedEruby 24.160000 1.280000 25.440000 ( 40.048199)
+Erubis::TinyEruby 31.690000 1.590000 33.280000 ( 49.862091)
+Erubis::TinyStdoutEruby 22.550000 1.230000 23.780000 ( 33.316978)
+Erubis::TinyPrintEruby 22.340000 1.150000 23.490000 ( 33.577150)
.____________________
This shows that:
@@ -1168,7 +1236,7 @@ This shows that:
.* Erubis::SimplifiedEruby (which incudes SimplifiedEnhander) is faster than ERuby.
.* String buffer (StringBufferEnhancer) is slower than array buffer (ArrayBufferEnhancer which Erubis::Eruby includes)
.* Using print statement or $stdout is faster than array buffer and string buffer.
-.* Erubis::SimplestEruby (at 'erubis/simples.rb') and it's subclasses are the fastest in all eRuby implementation.
+.* Erubis::TinyEruby (at 'erubis/tiny.rb') and it's subclasses are the fastest in all eRuby implementation.
diff --git a/lib/erubis.rb b/lib/erubis.rb
index 7cca5cb..75f4895 100644
--- a/lib/erubis.rb
+++ b/lib/erubis.rb
@@ -55,7 +55,7 @@
require 'erubis/engine'
require 'erubis/helper'
require 'erubis/enhancer'
-#require 'erubis/simplest'
+#require 'erubis/tiny'
require 'erubis/engine/ruby'
#require 'erubis/engine/enhanced' # enhanced eruby engines
#require 'erubis/engine/optimized' # generates optimized ruby code
diff --git a/lib/erubis/engine.rb b/lib/erubis/engine.rb
index 2724259..205b7b4 100644
--- a/lib/erubis/engine.rb
+++ b/lib/erubis/engine.rb
@@ -16,6 +16,41 @@ module Erubis
##
+ ## context object for Engine#evaluate
+ ##
+ ## ex.
+ ## template = <<'END'
+ ## Hello <%= @user %>!
+ ## <% for item in @list %>
+ ## - <%= item %>
+ ## <% end %>
+ ## END
+ ##
+ ## context = Erubis::Context.new
+ ## context[:user] = 'World'
+ ## context[:list] = ['aaa', 'bbb', 'ccc']
+ ##
+ ## eruby = Erubis::Eruby.new(template)
+ ## print eruby.evaluate(context)
+ ##
+ class Context
+
+ def [](key)
+ return instance_variable_get("@#{key}")
+ end
+
+ def []=(key, value)
+ return instance_variable_set("@#{key}", value)
+ end
+
+ def keys
+ return instance_variables.collect { |name| name[1,name.length-1] }
+ end
+
+ end
+
+
+ ##
## base engine class
##
class Engine
@@ -53,14 +88,18 @@ module Erubis
end
def result(_binding=TOPLEVEL_BINDING)
- _filename = @filename || '(erubis)'
- eval @src, _binding, _filename
+ return eval(@src, _binding, (@filename || '(erubis)'))
end
def evaluate(_context={})
- ## load _context data as local variables by eval
- eval _context.keys.inject("") { |s, k| s << "#{k.to_s} = _context[#{k.inspect}];" }
- return result(binding())
+ _filename = @filename || '(erubis)'
+ if _context.is_a?(Hash)
+ ## load _context data as local variables by eval
+ eval _context.keys.inject("") { |s, k| s << "#{k.to_s} = _context[#{k.inspect}];" }
+ return eval(@src, binding(), _filename)
+ else
+ return _context.instance_eval(@src, _filename)
+ end
end
DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
diff --git a/lib/erubis/main.rb b/lib/erubis/main.rb
index ff944ef..7a31b20 100644
--- a/lib/erubis/main.rb
+++ b/lib/erubis/main.rb
@@ -6,7 +6,7 @@
require 'yaml'
require 'erubis'
-require 'erubis/simplest'
+require 'erubis/tiny'
require 'erubis/engine/enhanced'
require 'erubis/engine/optimized'
require 'erubis/engine/ruby'
@@ -50,7 +50,7 @@ module Erubis
def execute(argv=ARGV)
## parse command-line options
- options, properties = parse_argv(argv, "hvsxTtSbE", "pcrfKIlae")
+ options, properties = parse_argv(argv, "hvsxTtSbEX", "pcrfKIlae")
filenames = argv
options[?h] = true if properties[:help]
@@ -84,66 +84,23 @@ module Erubis
## class name of Eruby
classname = options[?c]
- unless classname
- classname = lang =~ /\Axml(.*)/ ? "EscapedE#{$1}" : "E#{lang}"
- end
- begin
- klass = Erubis.const_get(classname)
- rescue NameError
- klass = nil
- end
- unless klass
- if lang
- msg = "-l #{lang}: invalid language name (class Erubis::#{classname} not found)."
- else
- msg = "-c #{classname}: invalid class name."
- end
- raise CommandOptionError.new(msg)
- end
+ klass = get_classobj(classname, lang)
## kanji code
$KCODE = options[?K] if options[?K]
## read context values from yaml file
yamlfiles = options[?f]
- if yamlfiles
- hash = {}
- yamlfiles.split(/,/).each do |yamlfile|
- str = yamlfile == '-' ? $stdin.read() : File.read(yamlfile)
- str = untabify(str) if options[?t]
- ydoc = YAML.load(str)
- unless ydoc.is_a?(Hash)
- raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
- end
- convert_mapping_key_from_string_to_symbol(ydoc) if options[?S]
- hash.update(ydoc)
- end
- #hash.update(context)
- context = hash
- else
- context = {}
- end
+ context = load_yamlfiles(yamlfiles, options)
## properties for engine
- properties[:pattern] = options[?p] if options[?p]
- properties[:trim] = false if options[?T]
+ properties[:pattern] = options[?p] if options[?p]
+ properties[:trim] = false if options[?T]
properties[:preamble] = properties[:postamble] = false if options[?b]
- ## enhancers
- enhancers = []
- if options[?e]
- enhancer_name = nil
- begin
- options[?e].split(/,/).each do |shortname|
- enhancers << Erubis.const_get("#{shortname}Enhancer")
- end
- rescue NameError
- raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-E' to show all enhancers).")
- end
- end
-
- ## create engine
+ ## create engine and extend enhancers
engine = klass.new(nil, properties)
+ enhancers = get_enhancers(options[?e])
enhancers.each do |enhancer|
engine.extend(enhancer)
engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
@@ -153,13 +110,12 @@ module Erubis
val = nil
if filenames && !filenames.empty?
filenames.each do |filename|
- #engine = klass.load_file(filename, properties)
engine.filename = filename
engine.compile!(File.read(filename))
print val if val = do_action(action, engine, context, options)
end
else
- #engine = klass.new(input, properties)
+ engine.filename = '(stdin)'
engine.compile!($stdin.read())
print val if val = do_action(action, engine, context, options)
end
@@ -200,6 +156,7 @@ Usage: #{command} [..options..] [file ...]
-f file.yaml : YAML file for context values (read stdin if filename is '-')
-t : expand tab character in YAML file
-S : convert mapping key from string to symbol in YAML file
+ -X : set mapping data in YAML file into instance variables
END
# -r library : require library
@@ -255,7 +212,8 @@ END
end
name = $1; value = $2
name = name.gsub(/-/, '_').intern
- value = value == nil ? true : to_value(value)
+ #value = value.nil? ? true : YAML.load(value) # error, why?
+ value = value.nil? ? true : YAML.load("---\n#{value}\n")
context[name] = value
#
else # options
@@ -284,19 +242,6 @@ END
return options, context
end
- def to_value(str)
- case str
- when nil, "null", "nil" ; return nil
- when "true", "yes" ; return true
- when "false", "no" ; return false
- when /\A\d+\z/ ; return str.to_i
- when /\A\d+\.\d+\z/ ; return str.to_f
- when /\/(.*)\// ; return Regexp.new($1)
- when /\A'.*'\z/, /\A".*"\z/ ; return eval(str)
- else ; return str
- end
- end
-
def untabify(text, width=8)
sb = ''
text.scan(/(.*?)\t/m) do |s, |
@@ -306,6 +251,62 @@ END
return $' ? (sb << $') : text
end
+ def get_classobj(classname, lang)
+ unless classname
+ classname = lang =~ /\Axml(.*)/ ? "EscapedE#{$1}" : "E#{lang}"
+ end
+ begin
+ klass = Erubis.const_get(classname)
+ rescue NameError
+ klass = nil
+ end
+ unless klass
+ if lang
+ msg = "-l #{lang}: invalid language name (class Erubis::#{classname} not found)."
+ else
+ msg = "-c #{classname}: invalid class name."
+ end
+ raise CommandOptionError.new(msg)
+ end
+ return klass
+ end
+
+ def get_enhancers(enhancer_names)
+ return [] unless enhancer_names
+ enhancers = []
+ shortname = nil
+ begin
+ enhancer_names.split(/,/).each do |shortname|
+ enhancers << Erubis.const_get("#{shortname}Enhancer")
+ end
+ rescue NameError
+ raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-E' to show all enhancers).")
+ end
+ return enhancers
+ end
+
+ def load_yamlfiles(yamlfiles, options)
+ hash = {}
+ return hash unless yamlfiles
+ yamlfiles.split(/,/).each do |yamlfile|
+ str = yamlfile == '-' ? $stdin.read() : File.read(yamlfile)
+ str = untabify(str) if options[?t]
+ ydoc = YAML.load(str)
+ unless ydoc.is_a?(Hash)
+ raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
+ end
+ convert_mapping_key_from_string_to_symbol(ydoc) if options[?S]
+ hash.update(ydoc)
+ end
+ if options[?X] # conver hash to context object
+ context = Context.new
+ hash.each { |name, value| context[name] = value }
+ else
+ context = hash
+ end
+ return context
+ end
+
def convert_mapping_key_from_string_to_symbol(ydoc)
if ydoc.is_a?(Hash)
ydoc.each do |key, val|
diff --git a/lib/erubis/simplest.rb b/lib/erubis/tiny.rb
index 151c521..d3a1a23 100644
--- a/lib/erubis/simplest.rb
+++ b/lib/erubis/tiny.rb
@@ -7,24 +7,20 @@
module Erubis
##
- ## the simplest implementation of eRuby
+ ## tiny and the simplest implementation of eRuby
##
## ex.
- ## eruby = SimplestEruby.new(File.read('example.rhtml'))
+ ## eruby = TinyEruby.new(File.read('example.rhtml'))
## print eruby.src # print ruby code
## print eruby.result(binding()) # eval ruby code
##
- class SimplestEruby
+ class TinyEruby
def initialize(input)
@src = compile(input)
end
attr_reader :src
- def result(binding=TOPLEVEL_BINDING)
- eval @src, binding
- end
-
EMBEDDED_PATTERN = /(.*?)<%(=+|\#)?(.*?)-?%>/m
def compile(input)
@@ -50,6 +46,10 @@ module Erubis
return text.gsub!(/['\\]/, '\\\\\&') || text
end
+ def result(binding=TOPLEVEL_BINDING)
+ eval @src, binding
+ end
+
end
end
diff --git a/test/test-bin.rb b/test/test-bin.rb
index 23537c3..f01632b 100644
--- a/test/test-bin.rb
+++ b/test/test-bin.rb
@@ -263,6 +263,39 @@ END
end
+ def test_context1 # -X
+ yamlfile = "test.context4.yaml"
+ #
+ @input = <<'END'
+user = <%= @user %>
+<% for item in @list %>
+ - <%= item %>
+<% end %>
+END
+ @expected = <<'END'
+user = World
+ - aaa
+ - bbb
+ - ccc
+END
+ @options = "-f #{yamlfile} -X "
+ #
+ yaml = <<-END
+user: World
+list:
+ - aaa
+ - bbb
+ - ccc
+END
+ File.open(yamlfile, 'w') { |f| f.write(yaml) }
+ begin
+ _test()
+ ensure
+ File.unlink(yamlfile) if test(?f, yamlfile)
+ end
+ end
+
+
def test_include1 # -I
dir = 'foo'
lib = 'bar'
diff --git a/test/test-erubis.rb b/test/test-erubis.rb
index 5c59ec2..3c6665b 100644
--- a/test/test-erubis.rb
+++ b/test/test-erubis.rb
@@ -11,7 +11,7 @@ require 'stringio'
require 'erubis'
require 'erubis/engine/enhanced'
require 'erubis/engine/optimized'
-require 'erubis/simplest'
+require 'erubis/tiny'
class ErubisTest < Test::Unit::TestCase
@@ -37,7 +37,7 @@ class ErubisTest < Test::Unit::TestCase
end if @chomp
if @testopt != 'load_file'
- if @klass == Erubis::SimplestEruby
+ if @klass == Erubis::TinyEruby
eruby = @klass.new(@input)
else
eruby = @klass.new(@input, @options)
@@ -55,8 +55,9 @@ class ErubisTest < Test::Unit::TestCase
return if @testopt == 'skip_output'
- context = {}
- context[:list] = list = ['<aaa>', 'b&b', '"ccc"']
+ list = ['<aaa>', 'b&b', '"ccc"']
+ context = @testopt == 'context' ? Erubis::Context.new : {}
+ context[:list] = list
case @testopt
when/\Aeval\(/
@@ -156,6 +157,24 @@ __END__
<ul><li><aaa></li><li>b&b</li><li>"ccc"</li>
</ul>
##
+- name: context1
+ testopt: context
+ input: |
+ <ul>
+ <% for item in @list %>
+ <li><%= item %></li>
+ <% end %>
+ </ul>
+ src: |
+ _out = []; _out << '<ul>
+ '; for item in @list
+ ; _out << ' <li>'; _out << ( item ).to_s; _out << '</li>
+ '; end
+ ; _out << '</ul>
+ ';
+ _out.join
+ output: *basic1_output
+##
- name: ignore1
input: |
<ul>
@@ -782,8 +801,8 @@ __END__
_out
output: *optimized4_input
##
-- name: simplest1
- class: SimplestEruby
+- name: tiny1
+ class: TinyEruby
testopt: result
input: |
<ul>