# {-# LANGUAGE CPP #-}
#
# #include "version-compatibility-macros.h"
#
# -- |
# -- Module      :  Prettyprinter
# -- Copyright   :  Daan Leijen (c) 2000, http://www.cs.uu.nl/~daan
# --                Max Bolingbroke (c) 2008, http://blog.omega-prime.co.uk
# --                David Luposchainsky (c) 2016, http://github.com/quchen
# -- License     :  BSD-style (see the file LICENSE.md)
# -- Maintainer  :  David Luposchainsky <dluposchainsky (λ) google>
# -- Stability   :  experimental
# -- Portability :  portable
# --
# -- = Overview
# --
# -- This module defines a prettyprinter to format text in a flexible and
# -- convenient way. The idea is to combine a 'Doc'ument out of many small
# -- components, then using a layouter to convert it to an easily renderable
# -- 'SimpleDocStream', which can then be rendered to a variety of formats, for
# -- example plain 'Text'.
# --
# -- The documentation consists of several parts:
# --
# --   1. Just below is some general information about the library.
# --   2. The actual library with extensive documentation and examples
# --   3. Migration guide for users familiar with (ansi-)wl-pprint
# --
# -- == Starting out
# --
# -- As a reading list for starters, some of the most commonly used functions in
# -- this module include '<>', 'hsep', '<+>', 'vsep', 'align', 'hang'. These cover
# -- many use cases already, and many other functions are variations or
# -- combinations of these.
# --
# -- = Simple example
# --
# -- Let’s prettyprint a simple Haskell type definition. First, intersperse @->@
# -- and add a leading @::@,
# --
# -- >>> :{
# -- >>> prettyprintType :: [Doc x] -> Doc x
# -- >>> prettyprintType = align . sep . zipWith (<+>) ("::" : repeat "->")
# -- >>> :}
# --
# -- The 'sep' function is one way of concatenating documents, there are multiple
# -- others, e.g. 'vsep', 'cat' and 'fillSep'. In our case, 'sep' space-separates
# -- all entries if there is space, and newlines if the remaining line is too
# -- short.
# --
# -- Second, prepend the name to the type,
# --
# -- >>> let prettyprintDeclaration n tys = pretty n <+> prettyprintType tys
# --
# -- Now we can define a document that contains some type signature:
# --
# -- >>> let doc = prettyprintDeclaration "example" ["Int", "Bool", "Char", "IO ()"]
# --
# -- This document can now be printed, and it automatically adapts to available
# -- space. If the page is wide enough (80 characters in this case), the
# -- definitions are space-separated,
# --
# -- >>> putDocW 80 doc
# -- example :: Int -> Bool -> Char -> IO ()
# --
# -- If we narrow the page width to only 20 characters, the /same document/
# -- renders vertically aligned:
# --
# -- >>> putDocW 20 doc
# -- example :: Int
# --         -> Bool
# --         -> Char
# --         -> IO ()
# --
# -- Speaking of alignment, had we not used 'align', the @->@ would be at the
# -- beginning of each line, and not beneath the @::@.
# --
# -- The 'Prettyprinter.Util.putDocW' renderer used here is from
# -- "Prettyprinter.Util".
# --
# -- = General workflow
# --
# -- @
# -- ╔══════════╗
# -- ║          ║                         ╭────────────────────╮
# -- ║          ║                         │ 'vsep', 'pretty', '<+>', │
# -- ║          ║                         │ 'nest', 'align', …     │
# -- ║          ║                         ╰─────────┬──────────╯
# -- ║          ║                                   │
# -- ║  Create  ║                                   │
# -- ║          ║                                   │
# -- ║          ║                                   ▽
# -- ║          ║                         ╭───────────────────╮
# -- ║          ║                         │        'Doc'        │
# -- ╠══════════╣                         │  (rich document)  │
# -- ║          ║                         ╰─────────┬─────────╯
# -- ║          ║                                   │
# -- ║          ║                                   │ Layout algorithms
# -- ║  Layout  ║                                   │ e.g. 'layoutPretty'
# -- ║          ║                                   ▽
# -- ║          ║                         ╭───────────────────╮
# -- ║          ║                         │  'SimpleDocStream'  │
# -- ╠══════════╣                         │ (simple document) │
# -- ║          ║                         ╰─────────┬─────────╯
# -- ║          ║                                   │
# -- ║          ║                                   ├─────────────────────────────╮
# -- ║          ║                                   │                             │ 'Prettyprinter.Render.Util.SimpleDocTree.treeForm'
# -- ║          ║                                   │                             ▽
# -- ║          ║                                   │                     ╭───────────────╮
# -- ║          ║                                   │                     │ 'Prettyprinter.Render.Util.SimpleDocTree.SimpleDocTree' │
# -- ║  Render  ║                                   │                     ╰───────┬───────╯
# -- ║          ║                                   │                             │
# -- ║          ║               ╭───────────────────┼─────────────────╮  ╭────────┴────────╮
# -- ║          ║               │                   │                 │  │                 │
# -- ║          ║               ▽                   ▽                 ▽  ▽                 ▽
# -- ║          ║       ╭───────────────╮   ╭───────────────╮   ╭───────────────╮   ╭───────────────╮
# -- ║          ║       │ ANSI terminal │   │  Plain 'Text'   │   │ other/custom  │   │     HTML      │
# -- ║          ║       ╰───────────────╯   ╰───────────────╯   ╰───────────────╯   ╰───────────────╯
# -- ║          ║
# -- ╚══════════╝
# -- @
# --
# -- = How the layout works
# --
# -- There are two key concepts to laying a document out: the available width, and
# -- 'group'ing.
# --
# -- == Available width
# --
# -- The page has a certain maximum width, which the layouter tries to not exceed,
# -- by inserting line breaks where possible. The functions given in this module
# -- make it fairly straightforward to specify where, and under what
# -- circumstances, such a line break may be inserted by the layouter, for example
# -- via the 'sep' function.
# --
# -- There is also the concept of /ribbon width/. The ribbon is the part of a line
# -- that is printed, i.e. the line length without the leading indentation. The
# -- layouters take a ribbon fraction argument, which specifies how much of a line
# -- should be filled before trying to break it up. A ribbon width of 0.5 in a
# -- document of width 80 will result in the layouter to try to not exceed @0.5*80 =
# -- 40@ (ignoring current indentation depth).
# --
# -- == Grouping
# --
# -- A document can be 'group'ed, which tells the layouter that it should attempt
# -- to collapse it to a single line. If the result does not fit within the
# -- constraints (given by page and ribbon widths), the document is rendered
# -- unaltered. This allows fallback definitions, so that we get nice results even
# -- when the original document would exceed the layout constraints.
# --
# -- = Things the prettyprinter /cannot/ do
# --
# -- Due to how the Wadler/Leijen algorithm is designed, a couple of things are
# -- unsupported right now, with a high possibility of having no sensible
# -- implementation without significantly changing the layout algorithm. In
# -- particular, this includes
# --
# --   * Leading symbols instead of just spaces for indentation, as used by the
# --     Linux @tree@ tool for example
# --   * Multi-column layouts, in particular tables with multiple cells of equal
# --     width adjacent to each other
# --
# -- = Some helpful tips
# --
# -- == Which kind of annotation should I use?
# --
# -- __Summary:__ Use semantic annotations for @'Doc'@, and after layouting map to
# -- backend-specific ones.
# --
# -- For example, suppose you want to prettyprint some programming language code.
# -- If you want keywords to be red, you should annotate the @'Doc'@ with a type
# -- that has a 'Keyword' field (without any notion of color), and then after
# -- layouting convert the annotations to map @'Keyword'@ to e.g. @'Red'@ (using
# -- @'reAnnotateS'@). The alternative that I /do not/ recommend is directly
# -- annotating the @'Doc'@ with 'Red'.
# --
# -- While both versions would superficially work equally well and would create
# -- identical output, the recommended way has two significant advantages:
# -- modularity and extensibility.
# --
# -- /Modularity:/ To change the color of keywords later, you have to touch one
# -- point, namely the mapping in @'reAnnotateS'@, where @'Keyword'@ is mapped to
# -- 'Red'. If you have @'annotate Red …'@ everywher, you’ll have to do a full
# -- text replacement, producing a large diff and touching lots of places for a
# -- very small change.
# --
# -- /Extensibility:/ Adding a different backend in the recommended version is
# -- simply adding another @'reAnnotateS'@ to convert the @'Doc'@ annotation to
# -- something else. On the other hand, if you have @'Red'@ as an annotation in
# -- the @'Doc'@ already and the other backend does not support anything red
# -- (think of plain text or a website where red doesn’t work well with the rest
# -- of the style), you’ll have to worry about what to map »redness« to, which has
# -- no canonical answer. Should it be omitted? What does »red« mean anyway –
# -- maybe keywords and variables are red, and you want to change only the color
# -- of variables?
# module Prettyprinter (
#     -- * Documents
#     Doc,
#
#     -- * Basic functionality
#     Pretty(..),
#     viaShow, unsafeViaShow,
#     emptyDoc, nest, line, line', softline, softline', hardline,
#
#     -- ** Primitives for alternative layouts
#     group, flatAlt,
#
#     -- * Alignment functions
#     --
#     -- | The functions in this section cannot be described by Wadler's original
#     -- functions. They align their output relative to the current output
#     -- position - in contrast to @'nest'@ which always aligns to the current
#     -- nesting level. This deprives these functions from being \'optimal\'. In
#     -- practice however they prove to be very useful. The functions in this
#     -- section should be used with care, since they are more expensive than the
#     -- other functions. For example, @'align'@ shouldn't be used to pretty print
#     -- all top-level declarations of a language, but using @'hang'@ for let
#     -- expressions is fine.
#     align, hang, indent, encloseSep, list, tupled,
#
#     -- * Binary functions
#     (<>), (<+>),
#
#     -- * List functions
#
#     -- | The 'sep' and 'cat' functions differ in one detail: when 'group'ed, the
#     -- 'sep's replace newlines wich 'space's, while the 'cat's simply remove
#     -- them. If you're not sure what you want, start with the 'sep's.
#
#     concatWith,
#
#     -- ** 'sep' family
#     --
#     -- | When 'group'ed, these will replace newlines with spaces.
#     hsep, vsep, fillSep, sep,
#     -- ** 'cat' family
#     --
#     -- | When 'group'ed, these will remove newlines.
#     hcat, vcat, fillCat, cat,
#     -- ** Others
#     punctuate,
#
#     -- * Reactive/conditional layouts
#     --
#     -- | Lay documents out differently based on current position and the page
#     -- layout.
#     column, nesting, width, pageWidth,
#
#     -- * Filler functions
#     --
#     -- | Fill up available space
#     fill, fillBreak,
#
#     -- * General convenience
#     --
#     -- | Useful helper functions.
#     plural, enclose, surround,
#
#     -- * Bracketing functions
#     --
#     -- | Enclose documents in common ways.
#     squotes, dquotes, parens, angles, brackets, braces,
#
#     -- * Named characters
#     --
#     -- | Convenience definitions for common characters
#     lparen, rparen, langle, rangle, lbrace, rbrace, lbracket, rbracket, squote,
#     dquote, semi, colon, comma, space, dot, slash, backslash, equals, pipe,
#
#     -- ** Annotations
#     annotate,
#     unAnnotate,
#     reAnnotate,
#     alterAnnotations,
#     unAnnotateS,
#     reAnnotateS,
#     alterAnnotationsS,
#
#     -- * Optimization
#     --
#     -- Render documents faster
#     fuse, FusionDepth(..),
#
#     -- * Layout
#     --
#     -- | Laying a 'Doc'ument out produces a straightforward 'SimpleDocStream'
#     -- based on parameters such as page width and ribbon size, by evaluating how
#     -- a 'Doc' fits these constraints the best. There are various ways to render
#     -- a 'SimpleDocStream'. For the common case of rendering a 'SimpleDocStream'
#     -- as plain 'Text' take a look at "Prettyprinter.Render.Text".
#     SimpleDocStream(..),
#     PageWidth(..), LayoutOptions(..), defaultLayoutOptions,
#     layoutPretty, layoutCompact, layoutSmart,
#     removeTrailingWhitespace,
#
#     -- * Migration guide
#     --
#     -- $migration
# ) where
#
#
#
# #if !(SEMIGROUP_MONOID_SUPERCLASS)
# import Data.Semigroup
# #endif
# import Prettyprinter.Internal
from .Internal import *
# import Prettyprinter.Symbols.Ascii
from .Symbols.Ascii import *
#
# -- $setup
# --
# -- (Definitions for the doctests)
# --
# -- >>> :set -XOverloadedStrings
# -- >>> import Prettyprinter.Render.Text
# -- >>> import Prettyprinter.Util
#
#
#
# -- $migration
# --
# -- There are 3 main ways to migrate:
# --
# --   1. Direct: just replace the previous package and fix the errors
# --   2. Using a drop-in replacement mimicking the API of the former module, see
# --      the @prettyprinter-compat-<former package>@ packages
# --   3. Using a converter from the old @Doc@ type to the new one, see the
# --      @prettyprinter-convert-<former package>@ packages
# --
# -- If you're already familiar with (ansi-)wl-pprint, you'll recognize many
# -- functions in this module, and they work just the same way. However, a couple
# -- of definitions are missing:
# --
# --   - @char@, @string@, @double@, … – these are all special cases of the
# --     overloaded @'pretty'@ function.
# --   - @\<$>@, @\<$$>@, @\</>@, @\<//>@ are special cases of
# --     @'vsep'@, @'vcat'@, @'fillSep'@, @'fillCat'@ with only two documents.
# --   - If you need 'String' output, use the backends in the
# --     "Prettyprinter.Render.String" module.
# --   - The /display/ functions are moved to the rendering submodules, for
# --     example conversion to plain 'Text' is in the
# --     "Prettyprinter.Render.Text" module.
# --   - The /render/ functions are called /layout/ functions.
# --   - @SimpleDoc@ was renamed to @'SimpleDocStream'@, in order to make it
# --     clearer in the presence of @SimpleDocTree@.
# --   - Instead of providing an own colorization function for each
# --     color\/intensity\/layer combination, they have been combined in 'color',
# --     'colorDull', 'bgColor', and 'bgColorDull' functions, which can be found
# --     in the ANSI terminal specific @prettyprinter-ansi-terminal@ package.