Custom pretty printer

From Wiki
Revision as of 08:22, 26 August 2009 by Matthijs (talk | contribs) (→‎Hooks: Update function declarations (prepare for next change))
Jump to navigation Jump to search

< 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 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.

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:

  1. For each line in the input:
    • If the line contains only whitespace:
      1. Call empty_line
    • Else:
      1. Call begin_of_line
      2. Call line to modify the current line.
      3. Call flush_line to process and output the current line.
      4. Call end_of_line

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:

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

Hooks

The following hooks are available to a pretty printer.

empty_line

 function visualizer.empty_line()

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.

begin_of_line

 function visualizer.begin_of_line(n)

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.

end_of_line

 function visualizer.end_of_line(n)

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.

line

 function visualizer.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 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.

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.
buffers.finish_state(state)
Reset the current color, given the current color state. Returns the new color state.
buffers.currentcolors
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.
buffers.commands
This variable contains a number of useful TeX commands. See buff-ini.lua 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 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!