Hi all,
Do you like eRuby? Do you want to customize ERB?
The following is 30 lines implementation of eRuby.
This will help you to get your own eRuby implementation.
class TinyEruby
def initialize(input=nil)
@src = convert(input) if input
end
attr_reader :src
def convert(input)
src = "_buf = '';" # preamble
input.scan(/(.*?)<%(=)?(.*?)%>/m) do |text, ch, code|
src << " _buf << '#{escape_text(text)}';" unless text.empty?
src << (ch == '=' ? " _buf << (#{code}).to_s" : code) << ';'
end
rest = $' || input
src << " _buf << '#{escape_text(rest)}';" unless rest.empty?
src << "\n_buf.to_s\n" # postamble
return src
end
def escape_text(text)
return text.gsub!(/['\\]/, '\\\\\&') || text
end
def result(_binding=TOPLEVEL_BINDING)
eval @src, _binding
end
end
Usage of TinyEruby is the same as ERB.
The above code may be slow in some cases, because long pattern
matching (‘(.*?)’ and $1) in convert() is not fast.
You can improve performance of TinyEruby to avoid long matching.
...
def convert(input)
src = "_buf = '';" # preamble
pos = 0
input.scan(/<%(=)?(.*?)%>/m) do |ch, code|
match = Regexp.last_match
len = match.begin(0) - pos
text = input[pos, len]
pos = match.end(0)
src << " _buf << '#{escape_text(text)}';" unless text.empty?
src << (ch == '=' ? " _buf << (#{code}).to_s" : code) << ';'
end
rest = $' || input
src << " _buf << '#{escape_text(rest)}';" unless rest.empty?
src << "\n_buf.to_s\n" # postamble
return src
end
...
These codes are released in public domain. You can use it freely.
See
http://www.kuwata-lab.com/support/2007/10/09/30-lines-implementation-of-eruby/
for details.