Page Contents
What is the diverter?
The diverter provides the functions which allow a script to print output to pages. By maintaining a stack of diverter objects inside Aranha, it also allows general functions to create strings more efficiently by printing output and returning the result rather than by concatenating strings together and returning the result. By default, Aranha buffers script output in a top-level diverter until the script completes.
How to use the diverter
There are four main functions to interface to the diverter, and some special markers to make these functions more pleasant to use.
divert()
This takes no parameters and returns no results. It creates a new diverter object and pushes it onto the top of the divert stack so that it is the active diverter.
undivert()
This takes no arguments and returns the result of collapsing the active diverter to a string. It also removes the top diverter from the stack, making the next-most-recent call to divert() the active diverter.
dprint()
This takes as many arguments as you care to give it and performs expression interpolation on the arguments before passing them to the diverter for inclusion in the final output.
Expression interpolation is the replacing of lua expressions enclosed in <@ and @> tokens with their result, expressed as a string. The expression can be any arbitrary Lua expression, such as a simple variable name or adding together of the results of two functions.
The special markers >> and << are equivalent to an implicit call to dprint, with everything between the markers being passed to dprint. lhtml files are implicitly wrapped in a pair of >> and <<, so that the default is having the file contents passed to dprint and lua code can be included with in pairs of << and >>
vdprint()
Almost the same as dprint(), but it does no expression interpolation, it just passes the arguments to the diverter as they are.
Examples
These examples should all give exactly the same output:
Basic Lua method
output = ""
for key, value in pairs(t) do
output = output.."<tr><td>"..key.."</td><td>"..value.."</td></tr>"
end
vdprint method
divert()
for key, value in pairs(t) do
vdprint("<tr><td>", key, "</td><td>", value, "</td></tr>")
end
output = undivert()
dprint method
divert()
for key, value in pairs(t) do
dprint("<tr><td><@key@></td><td><@value@></td></tr>")
end
output = undivert()
Implicit dprint method
divert()
for key, value in pairs(t) do
>><tr><td><@key@></td><td><@value@></td></tr><<
end
output = undivert()
Other examples
>>sin(theta) + cos(phi) = <@math.sin(theta) + math.cos(phi)@><<
>>Value of form entry "title": <@escapeEntities(param.title or "<no title supplied>")@><<
How the diverter works
The diverter maintains a stack of diverter objects which collect anything which is dprinted into tables for collection by an undivert() later.
divert() simply creates a new empty object and sets it to be the current diverter.
undivert() collects the strings in the diverter into a single string and returns it.
vdprint() inserts the given arguments one by one into the current diverter after passing them through tostring().
dprint() uses Lua's pattern matching to replace anything in <@ @> pairs with the resulting value of the expression, as illustrated by the following pseudo-code:
function read_value(t, v)
found, val = find_local_in_call_stack_using_debugger_interface(v)
if not found then val = globals[v] end
return val
end
function getValue(v)
fn = loadstring("return "..v)
proxy = {}
setmetatable(proxy, { __index = read_value })
setfenv(fn, proxy)
return tostring(fn())
end
function dprint(...)
for a in ipairs(arg) do
diverter.add(string.gsub(a, "%<%@ *(.-) *%@%>", getValue))
end
end