prettyprinter-1.7.1: A modern, easy to use, well-documented, extensible pretty-printer.
Safe Haskell Safe-Inferred
Language Haskell2010

Prettyprinter.Render.Tutorials.StackMachineTutorial

Description

Deprecated: Writing your own stack machine is probably more efficient and customizable; also consider using »renderSimplyDecorated(A)« instead

This module shows how to write a custom prettyprinter backend, based on directly converting a SimpleDocStream to an output format using a stack machine. For a tree serialization approach, which may be more suitable for certain output formats, see Prettyprinter.Render.Tutorials.TreeRenderingTutorial .

Rendering to ANSI terminal with colors is an important use case for stack machine based rendering.

The module is written to be readable top-to-bottom in both Haddock and raw source form.

Synopsis

The type of available markup

First, we define a set of valid annotations must be defined, with the goal of defining a Doc SimpleHtml . We will later define how to convert this to the output format ( Text ).

Convenience definitions

The rendering algorithm

With the annotation definitions out of the way, we can now define a conversion function from SimpleDocStream annotated with our SimpleHtml to the final Text representation.

There are two ways to render this; the simpler one is just using renderSimplyDecorated . However, some output formats require more complicated functionality, so we explore this explicitly with a simple example below. An example for something more complicated is ANSI terminal rendering, where on popping we need to regenerate the previous style, requiring a pop (discard current style) followed by a peek (regenerate previous style).

renderStackMachine :: SimpleDocStream SimpleHtml -> StackMachine Builder SimpleHtml () Source #

The StackMachine type defines a stack machine suitable for many rendering needs. It has two auxiliary parameters: the type of the end result, and the type of the document’s annotations.

Most StackMachine creations will look like this definition: a recursive walk through the SimpleDocStream , pushing styles on the stack and popping them off again, and writing raw output.

The equivalent to this in the tree based rendering approach is renderTree .

htmlTag :: SimpleHtml -> ( Builder , Builder ) Source #

Convert a SimpleHtml annotation to a pair of opening and closing tags. This is where the translation of style to raw output happens.

render :: SimpleDocStream SimpleHtml -> Text Source #

We can now wrap our stack machine definition from renderStackMachine in a nicer interface; on successful conversion, we run the builder to give us the final Text , and before we do that we check that the style stack is empty (i.e. there are no unmatched style applications) after the machine is run.

This function does only a bit of plumbing around renderStackMachine , and is the main API function of a stack machine renderer. The tree renderer equivalent to this is render .

Example invocation

We can now render an example document using our definitions:

>>> :set -XOverloadedStrings
>>> import qualified Data.Text.Lazy.IO as TL
>>> :{
>>> let go = TL.putStrLn . render . layoutPretty defaultLayoutOptions
>>> in go (vsep
>>> [ headline "Example document"
>>> , paragraph ("This is a" <+> color Red "paragraph" <> comma)
>>> , paragraph ("and" <+> bold "this text is bold.")
>>> ])
>>> :}
<h1>Example document</h1>
<p>This is a <span style="color: #f00">paragraph</span>,</p>
<p>and <strong>this text is bold.</strong></p>