Changes

Jump to navigation Jump to search
5,328 bytes added ,  13:56, 30 June 2009
Document custom prettyprinters in MkIV
< [[Verbatim_text]]

== Custom pretty printers ==
ConTeXt allows one to define a custom pretty printer, which knows how to
interpret and display a particular type of file, text or programming
language.

This page details the creation of a pretty printer in Lua, which is
possible with MkIV and [[LuaTeX]]. This page does not apply to MkII.

To create a custom pretty printer, you need to create a file named
<tt>pret-foo.lua</tt>, where <tt>foo</tt> is the name of the
prettyprinter. Fore more details about where to put this file and how to
use it, see [[Verbatim_text#Your_own_formatter]]. We'll focus here on
what to put in the file.

== Defining hooks ==
Each pretty printer should define a number of hook functions. Each of
these will be called at specific times during the pretty printing and
are free to handle the input in any way. Each hook is optional, if it is
not defined, a default version will be called instead.

When pretty printing, the following hooks are called:

# For each line in the input:
#* If the line contains only whitespace:
#*# Call <tt>empty_line</tt>
#* Else:
#*# Call <tt>begin_of_line</tt>
#*# Call <tt>line</tt> to modify the current line.
#*# Call <tt>flush_line</tt> to process and output the current line.
#*# Call <tt>end_of_line</tt>

Each hook should be defined as function named as follows:
<tt>buffers.visualizers.''printer_name''.''function_name''</tt>

For example, the <tt>flush_line</tt> function for the <tt>foo</tt>
pretty printer, above should be defined as:

function buffers.visualizers.foo.flush_line(str,nested)

== Hooks ==

The following hooks are available to a pretty printer.

===<tt>empty_line</tt>===

function buffers.visualizers.''printer_name''.empty_line()

This hook is called for every empty line in the output. The default
implementation just outputs an empty line, using the
<tt>buffers.commands.empty_line_command</tt>.

===<tt>begin_of_line</tt>===

function buffers.visualizers.''printer_name''.begin_of_line(n)

This hook is called at the start of every non-empty line. The only
argument, <tt>n</tt>, is the number of the line. The function should
return nothing (but use <tt>texprint</tt> and friends to produce
output).

The default implementation outputs an optional line number and some
other tex commands, using
<tt>buffers.commands.begin_of_line_command</tt>.

Note that the line number does not include empty lines. This is
configurable using the <tt>flags.count_empty_lines</tt> variable,
although there does not seem to be a way to set this flag using a
ConTeXt macro.

===<tt>end_of_line</tt>===

function buffers.visualizers.''printer_name''.end_of_line(n)

This hook is called at the end of every non-empty line. The function
should return nothing (but use <tt>texprint</tt> and friends to produce
output).

The default implementation outputs some tex commands using
<tt>buffers.commands.end_of_line_command</tt>.

===<tt>line</tt>===

function buffers.visualizers.''printer_name''.line(str)

This hook is called for every non-empty line. The first argument is the
line itself,. The function should return an updated line, which is then
passed to <tt>flush_line</tt>.

The default implementation just returns its argument unmodified.

It's not exactly clear to me what the purpose of this hook is. None of
the existing pretty printers seem to use it, they all do their work in
<tt>flush_line</tt>.

===<tt>flush_line</tt>===

function buffers.visualizers.''printer_name''.flush_line(str, nested)

This hook is called for every non-empty line. The first argument is the
line itself, as returned by the <tt>line</tt> hook. The second argument
is some indication of nested brackets in the input, but it's not
completely clear how this works.

The function should return nothing, but use <tt>texprint</tt> and
friends to produce output. Alternatively, the function could build a
table and pass that to <tt>buffers.flush_result</tt> (which also handles
some stuff related to nesting).

== Utility functions and variables ==
There are some utilities available for pretty printers. All of the below
are defined in <tt>buff-ini.lua</tt>, as well as some other stuff not
listed here.

;<tt>buffers.flush_result(result, nested)</tt>: Output all values in the given table <tt>result</tt>, while doing something with nesting.
;<tt>buffers.change_state(n, state)</tt>: Set the current color to n, given the current color state. Returns the new color state.
;<tt>buffers.finish_state(state)</tt>: Reset the current color, given the current color state. Returns the new color state.
;<tt>buffers.currentcolors</tt>: This is a table that maps color numbers (as passed to <tt>buffer.change_state</tt>) to TeX color names. A pretty printer using coloring should set this in its <tt>flush_line</tt>, for example.
;<tt>buffers.commands</tt>: This variable contains a number of useful TeX commands. See <tt>buff-ini.lua</tt> for details.

== More info ==
The above is not quite complete, some things are missing or
underdocumented. The code that drives the prettyprinting is in the file
<tt>buff-ini.lua</tt> (which is called by <tt>buff-ini.mkiv</tt> and
<tt>buff-ver.mkiv</tt> from the TeX side), in the ConTeXt distribution.
If you're missing anything, you'll probably find some answers there.
Don't forget to write down what you find on this page!
14

edits

Navigation menu