digital-scurf wikiAranha > Output Diverter

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