summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authormakoto kuwata <kwa@kuwata-lab.com>2006-01-29 12:24:10 +0000
committermakoto kuwata <kwa@kuwata-lab.com>2006-01-29 12:24:10 +0000
commit670ad2e8ceaf9383d0721bc5865fb1d4481f9ecc (patch)
tree7935e37d10da3fcf8f31a228abe52bbc5b230e71 /doc
parent9ae106b90202c4109ecd3cf4eae8de79a4488504 (diff)
downloaderubis-670ad2e8ceaf9383d0721bc5865fb1d4481f9ecc.tar.gz
- [bugfix] FastEruby prints empty text
- [bugfix] error occurs when input has no embedded pattern - [enhance] add bin/erubis - [enhance] add test/test-bin.rb - [change] rename XxxFixture to XxxEnhancer
Diffstat (limited to 'doc')
-rw-r--r--doc/eruby.html356
-rw-r--r--doc/eruby.txt246
2 files changed, 442 insertions, 160 deletions
diff --git a/doc/eruby.html b/doc/eruby.html
index 087c29c..60ae764 100644
--- a/doc/eruby.html
+++ b/doc/eruby.html
@@ -232,7 +232,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
rest.each_line do |line|
src &lt;&lt; "_out &lt;&lt; #{line.dump}" &lt;&lt; (line[-1] == ?\n ? "\n" : "; ")
end
@@ -249,13 +249,11 @@ example1.rb</div>
<pre class="program">list = ['aaa', 'bbb', 'ccc']
input = &lt;&lt;END
-&lt;table&gt;
+&lt;ul&gt;
&lt;% for item in list %&gt;
- &lt;tr&gt;
- &lt;td&gt;&lt;%= item %&gt;&lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;&lt;%= item %&gt;&lt;/li&gt;
&lt;% end %&gt;
-&lt;/table&gt;
+&lt;/ul&gt;
END
require 'eruby1'
@@ -268,30 +266,22 @@ puts eruby.result
<div class="output_caption">
output</div>
<pre class="output">--- source ---
-_out = ''; _out &lt;&lt; "&lt;table&gt;\n"
+_out = ''; _out &lt;&lt; "&lt;ul&gt;\n"
_out &lt;&lt; " "; for item in list ; _out &lt;&lt; "\n"
-_out &lt;&lt; " &lt;tr&gt;\n"
-_out &lt;&lt; " &lt;td&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/td&gt;\n"
-_out &lt;&lt; " &lt;/tr&gt;\n"
+_out &lt;&lt; " &lt;li&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/li&gt;\n"
_out &lt;&lt; " "; end ; _out &lt;&lt; "\n"
-_out &lt;&lt; "&lt;/table&gt;\n"
+_out &lt;&lt; "&lt;/ul&gt;\n"
_out
--- result ---
-&lt;table&gt;
+&lt;ul&gt;
- &lt;tr&gt;
- &lt;td&gt;aaa&lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;aaa&lt;/li&gt;
- &lt;tr&gt;
- &lt;td&gt;bbb&lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;bbb&lt;/li&gt;
- &lt;tr&gt;
- &lt;td&gt;ccc&lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;ccc&lt;/li&gt;
-&lt;/table&gt;
+&lt;/ul&gt;
</pre>
<br>
@@ -339,7 +329,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
<strong>add_src_text(src, rest)</strong>
<strong>finalize_src(src)</strong>
@@ -353,6 +343,7 @@ class Eruby
<strong>end</strong>
<strong>def add_src_text(src, text)</strong>
+ <strong>return if text.empty?</strong>
<strong>text.each_line do |line|</strong>
<strong>src &lt;&lt; "_out &lt;&lt; #{line.dump}" &lt;&lt; (line[-1] == ?\n ? "\n" : "; ")</strong>
<strong>end</strong>
@@ -401,6 +392,7 @@ fast-eruby.rb : 高速化した Eruby</div>
class FastEruby &lt; Eruby
def add_src_text(src, text)
+ return if text.empty?
src &lt;&lt; "_out &lt;&lt; #{text.dump}" &lt;&lt; "; "
src &lt;&lt; ("\n" * text.count("\n"))
end
@@ -423,16 +415,27 @@ input = &lt;&lt;END
END
require 'eruby2'
-require 'fast-eruby'
-eruby = FastEruby.new(input)
-puts "--- source ---"
+eruby = Eruby.new(input)
+puts "--- source (Eruby) ---"
puts eruby.src
-puts "--- result ---"
-puts eruby.result
+
+require 'fast-eruby'
+fasteruby = FastEruby.new(input)
+puts "--- source (FastEruby) ---"
+puts fasteruby.src
</pre>
<div class="output_caption">
output</div>
-<pre class="output">--- source ---
+<pre class="output">--- source (Eruby) ---
+_out = ''; _out &lt;&lt; "&lt;table&gt;\n"
+_out &lt;&lt; " "; for item in list ; _out &lt;&lt; "\n"
+_out &lt;&lt; " &lt;tr&gt;\n"
+_out &lt;&lt; " &lt;td&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/td&gt;\n"
+_out &lt;&lt; " &lt;/tr&gt;\n"
+_out &lt;&lt; " "; end ; _out &lt;&lt; "\n"
+_out &lt;&lt; "&lt;/table&gt;\n"
+_out
+--- source (FastEruby) ---
_out = ''; _out &lt;&lt; "&lt;table&gt;\n ";
for item in list ; _out &lt;&lt; "\n &lt;tr&gt;\n &lt;td&gt;";
@@ -441,22 +444,6 @@ _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/td&gt;\n &lt;/tr&gt;\n ";
end ; _out &lt;&lt; "\n&lt;/table&gt;\n";
_out
---- result ---
-&lt;table&gt;
-
- &lt;tr&gt;
- &lt;td&gt;aaa&lt;/td&gt;
- &lt;/tr&gt;
-
- &lt;tr&gt;
- &lt;td&gt;bbb&lt;/td&gt;
- &lt;/tr&gt;
-
- &lt;tr&gt;
- &lt;td&gt;ccc&lt;/td&gt;
- &lt;/tr&gt;
-
-&lt;/table&gt;
</pre>
<br>
@@ -522,7 +509,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
add_src_text(src, rest)
finalize_src(src)
@@ -536,6 +523,7 @@ class Eruby
end
def add_src_text(src, text)
+ return if text.empty?
text.each_line do |line|
src &lt;&lt; "_out &lt;&lt; #{line.dump}" &lt;&lt; (line[-1] == ?\n ? "\n" : "; ")
end
@@ -562,15 +550,12 @@ example3.rb</div>
<pre class="program">list = ['aaa', 'bbb', 'ccc']
input = &lt;&lt;END
-&lt;table&gt;
+&lt;ul&gt;
&lt;% for item in list %&gt;
- &lt;tr&gt;
- &lt;td&gt;
- &lt;%= item %&gt;
- &lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;
+ &lt;%= item %&gt;
+ &lt;/li&gt;
&lt;% end %&gt;
-&lt;/table&gt;
&lt;/ul&gt;
END
@@ -584,35 +569,25 @@ puts eruby.result
<div class="output_caption">
output</div>
<pre class="output">--- source ---
-_out = ''; _out &lt;&lt; "&lt;table&gt;\n"
+_out = ''; _out &lt;&lt; "&lt;ul&gt;\n"
for item in list
-_out &lt;&lt; " &lt;tr&gt;\n"
-_out &lt;&lt; " &lt;td&gt;\n"
-_out &lt;&lt; " "; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "\n"
-_out &lt;&lt; " &lt;/td&gt;\n"
-_out &lt;&lt; " &lt;/tr&gt;\n"
+_out &lt;&lt; " &lt;li&gt;\n"
+_out &lt;&lt; " "; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "\n"
+_out &lt;&lt; " &lt;/li&gt;\n"
end
-_out &lt;&lt; "&lt;/table&gt;\n"
_out &lt;&lt; "&lt;/ul&gt;\n"
_out
--- result ---
-&lt;table&gt;
- &lt;tr&gt;
- &lt;td&gt;
- aaa
- &lt;/td&gt;
- &lt;/tr&gt;
- &lt;tr&gt;
- &lt;td&gt;
- bbb
- &lt;/td&gt;
- &lt;/tr&gt;
- &lt;tr&gt;
- &lt;td&gt;
- ccc
- &lt;/td&gt;
- &lt;/tr&gt;
-&lt;/table&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>
<br>
@@ -679,7 +654,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
add_src_text(src, rest)
finalize_src(src)
@@ -693,6 +668,7 @@ class Eruby
end
def add_src_text(src, text)
+ return if text.empty?
text.each_line do |line|
src &lt;&lt; "_out &lt;&lt; #{line.dump}" &lt;&lt; (line[-1] == ?\n ? "\n" : "; ")
end
@@ -750,14 +726,12 @@ example4.rb</div>
<pre class="program">list = ['&lt;aaa&gt;', 'b&amp;b', '"ccc"']
input = &lt;&lt;END
-&lt;table&gt;
+&lt;ul&gt;
&lt;% for item in list %&gt;
- &lt;tr&gt;
- &lt;td&gt;&lt;%= item %&gt;&lt;/td&gt;
- &lt;td&gt;&lt;%== item %&gt;&lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;&lt;%= item %&gt;&lt;/li&gt;
+ &lt;li&gt;&lt;%== item %&gt;&lt;/li&gt;
&lt;% end %&gt;
-&lt;/table&gt;
+&lt;/ul&gt;
END
require 'eruby4'
@@ -771,30 +745,22 @@ puts eruby.result
<div class="output_caption">
output</div>
<pre class="output">--- source ---
-_out = ''; _out &lt;&lt; "&lt;table&gt;\n"
+_out = ''; _out &lt;&lt; "&lt;ul&gt;\n"
for item in list
-_out &lt;&lt; " &lt;tr&gt;\n"
-_out &lt;&lt; " &lt;td&gt;"; _out &lt;&lt; XmlEruby.escape( item ); _out &lt;&lt; "&lt;/td&gt;\n"
-_out &lt;&lt; " &lt;td&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/td&gt;\n"
-_out &lt;&lt; " &lt;/tr&gt;\n"
+_out &lt;&lt; " &lt;li&gt;"; _out &lt;&lt; XmlEruby.escape( item ); _out &lt;&lt; "&lt;/li&gt;\n"
+_out &lt;&lt; " &lt;li&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/li&gt;\n"
end
-_out &lt;&lt; "&lt;/table&gt;\n"
+_out &lt;&lt; "&lt;/ul&gt;\n"
_out
--- result ---
-&lt;table&gt;
- &lt;tr&gt;
- &lt;td&gt;&amp;lt;aaa&amp;gt;&lt;/td&gt;
- &lt;td&gt;&lt;aaa&gt;&lt;/td&gt;
- &lt;/tr&gt;
- &lt;tr&gt;
- &lt;td&gt;b&amp;amp;b&lt;/td&gt;
- &lt;td&gt;b&amp;b&lt;/td&gt;
- &lt;/tr&gt;
- &lt;tr&gt;
- &lt;td&gt;&amp;quot;ccc&amp;quot;&lt;/td&gt;
- &lt;td&gt;"ccc"&lt;/td&gt;
- &lt;/tr&gt;
-&lt;/table&gt;
+&lt;ul&gt;
+ &lt;li&gt;&amp;lt;aaa&amp;gt;&lt;/li&gt;
+ &lt;li&gt;&lt;aaa&gt;&lt;/li&gt;
+ &lt;li&gt;b&amp;amp;b&lt;/li&gt;
+ &lt;li&gt;b&amp;b&lt;/li&gt;
+ &lt;li&gt;&amp;quot;ccc&amp;quot;&lt;/li&gt;
+ &lt;li&gt;"ccc"&lt;/li&gt;
+&lt;/ul&gt;
</pre>
<br>
@@ -863,7 +829,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
add_src_text(src, rest)
finalize_src(src)
@@ -877,6 +843,7 @@ class Eruby
end
def add_src_text(src, text)
+ return if text.empty?
text.each_line do |line|
src &lt;&lt; "_out &lt;&lt; #{line.dump}" &lt;&lt; (line[-1] == ?\n ? "\n" : "; ")
end
@@ -903,13 +870,11 @@ example5.rb</div>
<pre class="program">list = ['aaa', 'bbb', 'ccc']
input = &lt;&lt;END
-&lt;table&gt;
+&lt;ul&gt;
&lt;!--% for item in list %--&gt;
- &lt;tr&gt;
- &lt;td&gt;&lt;!--%= item %--&gt;&lt;/td&gt;
- &lt;/tr&gt;
+ &lt;li&gt;&lt;!--%= item %--&gt;&lt;/li&gt;
&lt;!--% end %--&gt;
-&lt;/table&gt;
+&lt;/ul&gt;
END
require 'eruby5'
@@ -923,26 +888,165 @@ print eruby.result()
<div class="output_caption">
output</div>
<pre class="output">--- source ---
-_out = ''; _out &lt;&lt; "&lt;table&gt;\n"
+_out = ''; _out &lt;&lt; "&lt;ul&gt;\n"
for item in list
-_out &lt;&lt; " &lt;tr&gt;\n"
-_out &lt;&lt; " &lt;td&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/td&gt;\n"
-_out &lt;&lt; " &lt;/tr&gt;\n"
+_out &lt;&lt; " &lt;li&gt;"; _out &lt;&lt; ( item ).to_s; _out &lt;&lt; "&lt;/li&gt;\n"
end
-_out &lt;&lt; "&lt;/table&gt;\n"
+_out &lt;&lt; "&lt;/ul&gt;\n"
_out
--- result ---
-&lt;table&gt;
- &lt;tr&gt;
- &lt;td&gt;aaa&lt;/td&gt;
- &lt;/tr&gt;
- &lt;tr&gt;
- &lt;td&gt;bbb&lt;/td&gt;
- &lt;/tr&gt;
- &lt;tr&gt;
- &lt;td&gt;ccc&lt;/td&gt;
- &lt;/tr&gt;
-&lt;/table&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>
+<br>
+
+
+<a name="コンテキストを指定できるようにする"></a>
+<h2 class="section1">コンテキストを指定できるようにする</h2>
+<a name="eruby6.rb"></a>
+<div class="program_caption">
+eruby6.rb</div>
+<pre class="program">##
+## eRuby の実装
+##
+class Eruby
+
+ ## eRuby 形式の文字列を受け取る
+ def initialize(input, options={})
+ @input = input
+ @options = options
+ @pattern = options[:pattern] || '&lt;% %&gt;'
+ @src = compile(@input)
+ end
+ attr_reader :src
+
+ ## 実行した結果 (文字列) を返す
+ def result(binding=TOPLEVEL_BINDING)
+ filename = '(eruby)'
+ eval @src, binding, filename
+ end
+
+ <strong>## コンテキストを指定して result() を呼び出す</strong>
+ <strong>def evaluate(_context={})</strong>
+ <strong>_evalstr = ''</strong>
+ <strong>_context.keys.each do |key|</strong>
+ <strong>_evalstr &lt;&lt; "#{key.to_s} = _context[#{key.inspect}]\n"</strong>
+ <strong>end</strong>
+ <strong>eval _evalstr</strong>
+ <strong>return result(binding())</strong>
+ <strong>end</strong>
+
+ private
+
+ ## eRuby 形式の文字列を Ruby コードに変換する
+ def compile(input=@input)
+ src = ""
+ initialize_src(src)
+ prefix, postfix = @pattern.split() # 埋め込みパターン
+ regexp = /(.*?)(^[ \t]*)?#{prefix}(=*)(.*?)#{postfix}([ \t]*\r?\n)?/m
+ input.scan(regexp) do |text, head_space, kind, code, tail_space|
+ ## * &lt;%= %&gt; のときは、何もしない
+ ## * &lt;% %&gt; のときは、
+ ## * 前後が空白だけのときは、その空白を削除
+ ## * そうでないときは、何もしない(空白を残す)
+ flag_trim = kind.empty? &amp;&amp; head_space &amp;&amp; tail_space
+
+ ## テキストを処理
+ add_src_text(src, text)
+
+ ## 前の空白を処理
+ unless flag_trim
+ add_src_text(src, head_space) if head_space
+ end
+
+ ## 埋め込み Ruby コードを処理
+ if !kind.empty? # &lt;%= %&gt; の場合
+ add_src_expr(src, code, kind.length)
+ else # &lt;% %&gt; の場合
+ ## 改行を含めた前後の空白をコードに足す
+ code = "#{head_space}#{code}#{tail_space}" if flag_trim
+ add_src_code(src, code)
+ end
+
+ ## 後ろの空白を処理
+ unless flag_trim
+ add_src_text(src, tail_space) if tail_space
+ end
+ end
+
+ ## 残りのテキストを処理
+ rest = $' || input
+ add_src_text(src, rest)
+
+ finalize_src(src)
+ return src
+ end
+
+ protected
+
+ def initialize_src(src)
+ src &lt;&lt; "_out = ''; "
+ end
+
+ def add_src_text(src, text)
+ return if text.empty?
+ text.each_line do |line|
+ src &lt;&lt; "_out &lt;&lt; #{line.dump}" &lt;&lt; (line[-1] == ?\n ? "\n" : "; ")
+ end
+ end
+
+ def add_src_expr(src, code, length)
+ src &lt;&lt; "_out &lt;&lt; (#{code}).to_s; "
+ end
+
+ def add_src_code(src, code)
+ code.each_line { |line| src &lt;&lt; line }
+ src &lt;&lt; "; " unless code[-1] == ?\n
+ end
+
+ def finalize_src(src)
+ src &lt;&lt; "_out\n"
+ end
+
+end
+
+</pre>
+<a name="example6.rb"></a>
+<div class="program_caption">
+example6.rb</div>
+<pre class="program">## eRuby スクリプト
+input = &lt;&lt;END
+&lt;h2&gt;&lt;%= title %&gt;&lt;/h2&gt;
+&lt;ul&gt;
+ &lt;% for item in list %&gt;
+ &lt;li&gt;&lt;%= item %&gt;&lt;/li&gt;
+ &lt;% end %&gt;
+&lt;/ul&gt;
+END
+
+## コンテキストオブジェクトを作成する。
+## 変数名は文字列または Symbol で指定する。
+## また YAML ファイルを読み込んでそれをコンテキストとして使ってもよい。
+context = {}
+context['title'] = "Context Example"
+context[:list] = ['aaa', 'bbb', 'ccc']
+
+## eRuby を実行する
+require 'eruby6'
+eruby = Eruby.new(input)
+print eruby.evaluate(context)
+</pre>
+<div class="output_caption">
+output</div>
+<pre class="output">&lt;h2&gt;Context Example&lt;/h2&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>
<br>
diff --git a/doc/eruby.txt b/doc/eruby.txt
index bdd0ce9..d5098e3 100644
--- a/doc/eruby.txt
+++ b/doc/eruby.txt
@@ -48,7 +48,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
rest.each_line do |line|
src << "_out << #{line.dump}" << (line[-1] == ?\n ? "\n" : "; ")
end
@@ -66,13 +66,18 @@ end
list = ['aaa', 'bbb', 'ccc']
input = <<END
-<table>
+<ul>
<% for item in list %>
- <tr>
- <td><%= item %></td>
- </tr>
+ <li><%= item %></li>
<% end %>
-</table>
+</ul>
+.#<table>
+.# <% for item in list %>
+.# <tr>
+.# <td><%= item %></td>
+.# </tr>
+.# <% end %>
+.#</table>
END
require 'eruby1'
@@ -134,7 +139,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
{{*add_src_text(src, rest)*}}
{{*finalize_src(src)*}}
@@ -148,6 +153,7 @@ class Eruby
{{*end*}}
{{*def add_src_text(src, text)*}}
+ {{*return if text.empty?*}}
{{*text.each_line do |line|*}}
{{*src << "_out << #{line.dump}" << (line[-1] == ?\n ? "\n" : "; ")*}}
{{*end*}}
@@ -174,7 +180,7 @@ end
.-------------------- stdout-eruby.rb
##
## 文字列ではなく標準出力を使う Eruby
-## (「<% print var %>」が問題なく使えるようになる)
+## (「<% print expr %>」が使えるようになる)
##
class StdoutEruby < Eruby
@@ -198,6 +204,7 @@ end
class FastEruby < Eruby
def add_src_text(src, text)
+ return if text.empty?
src << "_out << #{text.dump}" << "; "
src << ("\n" * text.count("\n"))
end
@@ -211,6 +218,11 @@ end
list = ['aaa', 'bbb', 'ccc']
input = <<END
+.#<ul>
+.# <% for item in list %>
+.# <li><%= item %></li>
+.# <% end %>
+.#</ul>
<table>
<% for item in list %>
<tr>
@@ -221,12 +233,14 @@ input = <<END
END
require 'eruby2'
-require 'fast-eruby'
-eruby = FastEruby.new(input)
-puts "--- source ---"
+eruby = Eruby.new(input)
+puts "--- source (Eruby) ---"
puts eruby.src
-puts "--- result ---"
-puts eruby.result
+
+require 'fast-eruby'
+fasteruby = FastEruby.new(input)
+puts "--- source (FastEruby) ---"
+puts fasteruby.src
.--------------------
.? output
@@ -297,7 +311,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
add_src_text(src, rest)
finalize_src(src)
@@ -311,6 +325,7 @@ class Eruby
end
def add_src_text(src, text)
+ return if text.empty?
text.each_line do |line|
src << "_out << #{line.dump}" << (line[-1] == ?\n ? "\n" : "; ")
end
@@ -338,16 +353,22 @@ end
list = ['aaa', 'bbb', 'ccc']
input = <<END
-<table>
+<ul>
<% for item in list %>
- <tr>
- <td>
- <%= item %>
- </td>
- </tr>
+ <li>
+ <%= item %>
+ </li>
<% end %>
-</table>
</ul>
+.#<table>
+.# <% for item in list %>
+.# <tr>
+.# <td>
+.# <%= item %>
+.# </td>
+.# </tr>
+.# <% end %>
+.#</table>
END
require 'eruby3'
@@ -426,7 +447,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
add_src_text(src, rest)
finalize_src(src)
@@ -440,6 +461,7 @@ class Eruby
end
def add_src_text(src, text)
+ return if text.empty?
text.each_line do |line|
src << "_out << #{line.dump}" << (line[-1] == ?\n ? "\n" : "; ")
end
@@ -499,14 +521,20 @@ end
list = ['<aaa>', 'b&b', '"ccc"']
input = <<END
-<table>
+<ul>
<% for item in list %>
- <tr>
- <td><%= item %></td>
- <td><%== item %></td>
- </tr>
+ <li><%= item %></li>
+ <li><%== item %></li>
<% end %>
-</table>
+</ul>
+.#<table>
+.# <% for item in list %>
+.# <tr>
+.# <td><%= item %></td>
+.# <td><%== item %></td>
+.# </tr>
+.# <% end %>
+.#</table>
END
require 'eruby4'
@@ -591,7 +619,7 @@ class Eruby
end
## 残りのテキストを処理
- rest = $'
+ rest = $' || input
add_src_text(src, rest)
finalize_src(src)
@@ -605,6 +633,7 @@ class Eruby
end
def add_src_text(src, text)
+ return if text.empty?
text.each_line do |line|
src << "_out << #{line.dump}" << (line[-1] == ?\n ? "\n" : "; ")
end
@@ -632,13 +661,18 @@ end
list = ['aaa', 'bbb', 'ccc']
input = <<END
-<table>
+<ul>
<!--% for item in list %-->
- <tr>
- <td><!--%= item %--></td>
- </tr>
+ <li><!--%= item %--></li>
<!--% end %-->
-</table>
+</ul>
+.#<table>
+.# <!--% for item in list %-->
+.# <tr>
+.# <td><!--%= item %--></td>
+.# </tr>
+.# <!--% end %-->
+.#</table>
END
require 'eruby5'
@@ -656,3 +690,147 @@ print eruby.result()
.<<<:! ruby example5.rb
.____________________
+
+
+
+●コンテキストを指定できるようにする
+
+.? eruby6.rb
+.-------------------- eruby6.rb
+##
+## eRuby の実装
+##
+class Eruby
+
+ ## eRuby 形式の文字列を受け取る
+ def initialize(input, options={})
+ @input = input
+ @options = options
+ @pattern = options[:pattern] || '<% %>'
+ @src = compile(@input)
+ end
+ attr_reader :src
+
+ ## 実行した結果 (文字列) を返す
+ def result(binding=TOPLEVEL_BINDING)
+ filename = '(eruby)'
+ eval @src, binding, filename
+ end
+
+ {{*## コンテキストを指定して result() を呼び出す*}}
+ {{*def evaluate(_context={})*}}
+ {{*_evalstr = ''*}}
+ {{*_context.keys.each do |key|*}}
+ {{*_evalstr << "#{key.to_s} = _context[#{key.inspect}]\n"*}}
+ {{*end*}}
+ {{*eval _evalstr*}}
+ {{*return result(binding())*}}
+ {{*end*}}
+
+ private
+
+ ## eRuby 形式の文字列を Ruby コードに変換する
+ def compile(input=@input)
+ src = ""
+ initialize_src(src)
+ prefix, postfix = @pattern.split() # 埋め込みパターン
+ regexp = /(.*?)(^[ \t]*)?#{prefix}(=*)(.*?)#{postfix}([ \t]*\r?\n)?/m
+ input.scan(regexp) do |text, head_space, kind, code, tail_space|
+ ## * <%= %> のときは、何もしない
+ ## * <% %> のときは、
+ ## * 前後が空白だけのときは、その空白を削除
+ ## * そうでないときは、何もしない(空白を残す)
+ flag_trim = kind.empty? && head_space && tail_space
+
+ ## テキストを処理
+ add_src_text(src, text)
+
+ ## 前の空白を処理
+ unless flag_trim
+ add_src_text(src, head_space) if head_space
+ end
+
+ ## 埋め込み Ruby コードを処理
+ if !kind.empty? # <%= %> の場合
+ add_src_expr(src, code, kind.length)
+ else # <% %> の場合
+ ## 改行を含めた前後の空白をコードに足す
+ code = "#{head_space}#{code}#{tail_space}" if flag_trim
+ add_src_code(src, code)
+ end
+
+ ## 後ろの空白を処理
+ unless flag_trim
+ add_src_text(src, tail_space) if tail_space
+ end
+ end
+
+ ## 残りのテキストを処理
+ rest = $' || input
+ add_src_text(src, rest)
+
+ finalize_src(src)
+ return src
+ end
+
+ protected
+
+ def initialize_src(src)
+ src << "_out = ''; "
+ end
+
+ def add_src_text(src, text)
+ return if text.empty?
+ text.each_line do |line|
+ src << "_out << #{line.dump}" << (line[-1] == ?\n ? "\n" : "; ")
+ end
+ end
+
+ def add_src_expr(src, code, length)
+ src << "_out << (#{code}).to_s; "
+ end
+
+ def add_src_code(src, code)
+ code.each_line { |line| src << line }
+ src << "; " unless code[-1] == ?\n
+ end
+
+ def finalize_src(src)
+ src << "_out\n"
+ end
+
+end
+
+.--------------------
+
+
+.? example6.rb
+.-------------------- example6.rb
+## eRuby スクリプト
+input = <<END
+<h2><%= title %></h2>
+<ul>
+ <% for item in list %>
+ <li><%= item %></li>
+ <% end %>
+</ul>
+END
+
+## コンテキストオブジェクトを作成する。
+## 変数名は文字列または Symbol で指定する。
+## また YAML ファイルを読み込んでそれをコンテキストとして使ってもよい。
+context = {}
+context['title'] = "Context Example"
+context[:list] = ['aaa', 'bbb', 'ccc']
+
+## eRuby を実行する
+require 'eruby6'
+eruby = Eruby.new(input)
+print eruby.evaluate(context)
+.--------------------
+
+
+.? output
+.____________________
+.<<<:! ruby example6.rb
+.____________________