Module documentation for 1.7.0
A modern Wadler/Leijen Prettyprinter
A prettyprinter/text rendering engine. Easy to use, well-documented, ANSI
terminal backend exists, HTML backend is trivial to implement, no name clashes,
let prettyType = align . sep . zipWith (<+>) ("::" : repeat "->") prettySig name ty = pretty name <+> prettyType ty in prettySig "example" ["Int", "Bool", "Char", "IO ()"]
-- Output for wide enough formats: example :: Int -> Bool -> Char -> IO () -- Output for narrow formats: example :: Int -> Bool -> Char -> IO ()
Longer; want to read
This package defines a prettyprinter to format text in a flexible and convenient
way. The idea is to combine a document out of many small components, then using
a layouter to convert it to an easily renderable simple document, which can then
be rendered to a variety of formats, for example plain
Text, or Markdown.
What you are reading right now was generated by this library (see
Why another prettyprinter?
Haskell, more specifically Hackage, has a zoo of Wadler/Leijen based
prettyprinters already. Each of them addresses a different concern with the
wl-pprint package. This package solves all these issues, and then
Text instead of
String has exactly one use, and that’s showing Hello World in tutorials. For
all other uses,
Text is what people should be using. The prettyprinter uses no
String definitions anywhere; using a
String means an immediate conversion to
The library is stuffed with runnable examples, showing use cases for the vast majority of exported values. Many things reference related definitions, everything comes with at least a sentence explaining its purpose.
No name clashes
Many prettyprinters use the legacy API of the first Wadler/Leijen prettyprinter,
which used e.g.
(<$>) to separate lines, which clashes with the ubiquitous
fmap that’s been in Base for ages. These definitions were either
removed or renamed, so there are no name clashes with standard libraries
Text is not all letters and newlines. Often, we want to add more information, the simplest kind being some form of styling. An ANSI terminal supports coloring, a web browser a plethora of different formattings.
More complex uses of annotations include e.g. adding type annotations for mouse-over hovers when printing a syntax tree, adding URLs to documentation, or adding source locations to show where a certain piece of output comes from. Idris is a project that makes extensive use of such a feature.
Special care has been applied to make annotations unobtrusive, so that if you don’t need or care about them there is no overhead, neither in terms of usability nor performance.
A document can be rendered in many different ways, for many different clients. There is plain text, there is the ANSI terminal, there is the browser. Each of these speak different languages, and the backend is responsible for the translation to those languages. Backends should be readily available, or easy to implement if a custom solution is desired.
As a result, each backend requires only minimal dependencies; if you don’t want to print to an ANSI terminal for example, there is no need to have a dependency on a terminal library.
Rendering large documents should be done efficiently, and the library should make it easy to optimize common use cases for the programmer.
The type of documents is abstract in most of the other Wadler/Leijen
prettyprinters, making it hard to impossible to write adaptors from one library
to another. The type should be exposed for such purposes so it is possible to
write adaptors from library to library, or each of them is doomed to live on its
own small island of incompatibility. For this reason, the
Doc type is fully
exposed in a semi-internal module for this specific use case.
The prettyprinter family
prettyprinter family of packages consists of:
prettyprinteris the core package. It defines the language to generate nicely laid out documents, which can then be given to renderers to display them in various ways, e.g. HTML, or plain text.
prettyprinter-ansi-terminalprovides a renderer suitable for ANSI terminal output including colors (at the cost of a dependency more).
prettyprinter-compat-wl-pprintprovides a drop-in compatibility layer for previous users of the
wl-pprintpackage. Use it for easy adaption of the new
prettyprinter, but don’t develop anything new with it.
prettyprinter-compat-ansi-wl-pprintis the same, but for previous users of
prettyprinter-compat-annotated-wl-pprintis the same, but for previous users of
prettyprinter-convert-ansi-wl-pprintis a converter, not a drop-in replacement, for documents generated by
ansi-wl-pprint. Useful for interfacing with other libraries that use the other format, like Trifecta and Optparse-Applicative.
Differences to the old Wadler/Leijen prettyprinters
The library originally started as a fork of
ansi-wl-pprint until every line
had been touched. The result is still in the same spirit as its predecessors,
but modernized to match the current ecosystem and needs.
The most significant changes are:
(<$>)is removed as an operator, since it clashes with the common alias for
- All but the essential
<+>operators were removed or replaced by ordinary names.
- Everything extensively documented, with references to other functions and runnable code examples.
- Use of
fusefunction to optimize often-used documents before rendering for efficiency.
- SimpleDoc was renamed
SimpleDocStream, to contrast the new
- In the ANSI backend, instead of providing an own colorization function for
each color/intensity/layer combination, they have been combined in
bgColorDullfunctions, which can be found in the ANSI terminal specific
This module is based on previous work by Daan Leijen and Max Bolingbroke, who implemented and significantly extended the prettyprinter given by a paper by Phil Wadler in his 1997 paper »A Prettier Printer«, by adding lots of convenience functions, styling, and new functionality. Their package, ansi-wl-pprint is widely used in the Haskell ecosystem, and is at the time of writing maintained by Edward Kmett.
layoutSmartso they don’t produce trailing whitespace as a result of indenting empty lines.
- Users of
removeTrailingWhitespaceshould check whether it is still needed.
- Users of
roundto compute ribbon width.
- Remove deprecated
- Add optimized implementation of
- Generalize the type of
layoutCompactto clarify that it doesn’t preserve annotations.
- Add strictness annotations in
- Add shallower
Prettyprintermodule hierarchy exposing the same API.
- The current plan for the existing
- Start deprecation in early 2021.
- Remove the modules after a deprecation period of at least one year.
- The current plan for the existing
- Fix build with GHC 7.4.
- Various documentation improvements.
- Speed up rendering to lazy and strict
- Documentation improvements for
- Internal refactoring of the
- Slightly reduce the scope of the fitting predicates for some edge cases.
- Use an export list in
- Speed up
- Improve generating spaces for indentation and
- Simplify some
Docconstants by defining them as
- Various documentation fixes and improvements.
fuse’s handling of annotated documents:
- Don’t remove annotations on empty documents.
- Apply fusion within annotations.
- Fix layouting of hard linebreaks with
- Speed up
groupfor documents containing linebreaks and previously
- Add debugging helpers in
- Documentation improvements and fixes
- Removing trailing whitespace sometimes restored necessary whitespace in the wrong spot
- Fix inconsistent formatting within align and wide sub-docs on narrow layouts
- Add fixity declaration to
- Fix removal of trailing whitespace
- Support Stack 2
- Add alignment to Pretty [a] instance
- Fix removal of blank lines in
- Widened support for GHC versions 7.4–8.8
- Fix dependency of doctest suite
- Add function to trim trailing space in layouted
unAnnotateS), which removed pushing, but not popping, style frames. This led to them throwing errors in pretty much all use cases.
encloseSepdoes no longer include an
alignwrapper; in other words,
encloseSep_old … = align (encloseSep_new …)
Change the default ribbon fraction to 1 (was 0.4)
unsafeViaShowfrom the public module
layoutSmartbehaving as if there was no space left for unbounded pages
panicPoppedEmptyto the panic module
- Rendering directly to a handle is now more efficient in the
Textrenderer, since no intermediate
Textis generated anymore.
- Remove upper version bounds from
alterAnnotationsto convert one annotation to multiple ones, to support e.g.
Keyword ---> Green+Bold
Doc: the implicit un-annotation done by it did more harm than good.
alterAnnotations, which allows changing or removing annotations.
unAnnotateare now special cases of this.
- Fix »group« potentially taking exponential time, by making the (internal)
flattenfunction detect whether it is going to have any effect inside
- Add proper version bounds for all dependencies and backport them to version 1
- Haddock: example for
- Add Foldable/Traversable instances for
- Add Functor instances for
- Add the simplified renderers
renderSimplyDecoratedAto the tree and stack renderer modules
- Lots of typo fixes and doc tweaks
- Add a changelog :-)