Custom pretty printer
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 pret-foo.lua, where foo 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.
Registering a new pretty printer
To let the pretty printer core know about your pretty printer, you need
to register it first. You do this by calling the
visualizer = buffers.newvisualizer('foo')
Here, you pass the name of the pretty printer, which is the (lowercase)
version of the first argument to
This function returns an (empty) table, into which you should store the
hook functions for any hooks you want to override. You can do this by
simply declaring the function with
visualizer as the first
component of the name (or whatever you assigned the return value from
newvisualizer to). Each of the function headers in the hook
list below use this.
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 empty_line
- Call begin_of_line
- Call line to modify the current line.
- Call flush_line to process and output the current line.
- Call end_of_line
- If the line contains only whitespace:
Each hook should be defined as function named as follows: buffers.visualizers.printer_name.function_name
For example, the flush_line function for the foo pretty printer, above should be defined as:
The following hooks are available to a pretty printer.
This hook is called for every empty line in the output. The default implementation just outputs an empty line, using the buffers.commands.empty_line_command.
This hook is called at the start of every non-empty line. The only argument, n, is the number of the line. The function should return nothing (but use texprint and friends to produce output).
The default implementation outputs an optional line number and some other tex commands, using buffers.commands.begin_of_line_command.
Note that the line number does not include empty lines. This is configurable using the flags.count_empty_lines variable, although there does not seem to be a way to set this flag using a ConTeXt macro.
This hook is called at the end of every non-empty line. The function should return nothing (but use texprint and friends to produce output).
The default implementation outputs some tex commands using buffers.commands.end_of_line_command.
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 flush_line.
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 flush_line.
function visualizer.flush_line(str, nested)
This hook is called for every non-empty line. The first argument is the line itself, as returned by the line 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 texprint and friends to produce output. Alternatively, the function could build a table and pass that to buffers.flush_result (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 buff-ini.lua, as well as some other stuff not listed here.
- buffers.flush_result(result, nested)
- Output all values in the given table result, while doing something with nesting.
- buffers.change_state(n, state)
- Set the current color to n, given the current color state. Returns the new color state.
- Reset the current color, given the current color state. Returns the new color state.
- This is a table that maps color numbers (as passed to buffer.change_state) to TeX color names. A pretty printer using coloring should set this in its flush_line, for example.
- This variable contains a number of useful TeX commands. See buff-ini.lua for details.
The above is not quite complete, some things are missing or underdocumented. The code that drives the prettyprinting is in the file buff-ini.lua (which is called by buff-ini.mkiv and buff-ver.mkiv 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!