class Temple::Generator
_buf << foo.downcase
foo = “More content”
_buf << “Some content”
# is the same as:
[:dynamic, “foo.downcase”]]
[:capture, “foo”, [:static, “More content”]],
[:static, “Some content”],
[:multi,
Example:
result, it sets the content to the variable given.
Evaluates the Sexp using the rules above, but instead of appending to the
=== [:capture, variable_name, sexp]
Newline causes a newline in the generated code, but not in the result.
=== [:newline]
change the control flow. Any n causes a newline in the generated code.
Block indicates that the given Ruby code should be evaluated, and may
=== [:block, ruby]
it to eval() and it would not raise SyntaxError.
The Ruby code must be a complete expression in the sense that you can pass
appended to the result.
Dynamic indicates that the given Ruby code should be evaluated and then
=== [:dynamic, ruby]
_buf << “HellonWorld”
# is the same as
[:static, “Hello n World”]
_buf << “Hello World”
# is the same as:
[:static, “Hello World”]
Example:
Static indicates that the given string should be appended to the result.
=== [:static, string]
[:dynamic, “@world”]]
[:static, “Hello ”],
[:multi,
several others sexps:
Multi is what glues everything together. It’s simply a sexp which combines
=== [:multi, *sexp]
of view) spits out. It’s what happens if you evaluate the generated code.
Then there’s the result. This is what your engine (from the user’s point
make exceptions report correct line numbers, which is very convenient.
point of view) spits out. If you construct this carefully enough, you can
First we have the generated code. This is what your engine (from Temple’s
When compiling, there’s two different strings we’ll have to think about.
multi, static, dynamic, block, newline and capture.
to. Currently it consists of four essential and two convenient types:
The core abstraction is what every template evetually should be compiled
== The Core Abstraction
def buffer
def buffer options[:buffer] end
def compile(exp)
def compile(exp) [preamble, compile!(exp), postamble].join(' ; ') end
def compile!(exp)
def compile!(exp) type, *args = exp send("on_#{type}", *args) end
def concat(str)
def concat(str) "#{buffer} << (#{str})" end
def on_capture(name, block)
def on_capture(name, block) options[:capture_generator].new(:buffer => name).compile(block) end
def on_multi(*exp)
def on_multi(*exp) exp.map { |e| compile!(e) }.join(' ; ') end
def on_newline
def on_newline "\n" end