Trivial example of LuaTeX’s post_linebreak_filter

LuaTeX provides a very interesting facility called “callbacks”. A callback is a Lua function that you provide and which LuaTeX will call at certain times during the course of processing your document. LuaTeX defines a number of callback opportunities which are detailed in the LuaTeX Reference Manual.

To use callbacks you have to provide the Lua function and then register it with LuaTeX so that it knows to call your function at the appropriate time. You can provide callbacks for many purposes such as reading input files, processing input buffers, hooking into line breaking, page building and so forth.

Callbacks are an exceptionally powerful concept and they open the door to very sophisticated document processing solutions. For example, you can hook into the internal node lists and process them to achieve special effects. Here is a very simple and short “plain TeX” example of hooking into LuaTeX’s post_linebreak_filter (and, in addition, playing with setting the page size).

To quote the LuaTeX Reference Manual

post_linebreak_filter: This callback is called just after LuaTEX has converted a list of nodes into a stack of \hboxes.

In the following example, just after LuaTeX has processed the vbox, and broken the paragraph into lines, it calls a Lua function called linelist which simply ships out each line in the paragraph. Also, and not part of the callback, a copy of the vbox is output on the last page, setting the page size to be that of the vbox.

\pdfoutput=1
\hoffset-1in
\voffset-1in
\nopagenumbers
\directlua{
linelist=function(head)
local boxer=200
for line in node.traverse_id('hlist',head) do
           tex.setbox(boxer, node.copy(line))
           tex.box[boxer].height= tex.box[boxer].height+65536 %add 65536sp = 1pt to avoid clipping
           tex.box[boxer].depth= tex.box[boxer].depth+65536 %add 65536sp = 1pt to avoid clipping
           tex.shipout(boxer)
end
return head
end
callback.register("post_linebreak_filter",linelist)
}

\setbox1000=\vbox{\hsize=50mm Let us examine the structure of a list of hboxes in a vbox because
it is an instructive thing to do.}
\pdfpagewidth=\wd1000
\vsize=\ht1000
\advance\vsize by 65536 sp
\pdfpageheight=\vsize
\box1000
\bye

The output

The output is a 5-page PDF: the first four pages are the individual lines in the typeset paragraph and the final page is the vbox.