-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Pretty-printing library -- -- This package contains a pretty-printing library, a set of API's that -- provides a way to easily print out text in a consistent format of your -- choosing. This is useful for compilers and related tools. . This -- library produces more compact outputs than both Wadler-Leijen or -- Hughes-PJ algorithms, at the expense of computational ressources. The -- core API is based on Hughes-PJ, but some combinators of the Leijen API -- are implemented as well. @package pretty-compact @version 3.1 module Text.PrettyPrint.Compact.Core type Annotation a = (Monoid a) class Layout d text :: (Layout d, Monoid a) => String -> d a flush :: (Layout d, Monoid a) => d a -> d a -- | <> new annotation to the Doc. -- -- Example: 'Any True' annotation will transform the rendered Doc -- into uppercase: -- --
-- >>> let r = putStrLn . renderWith defaultOptions { optsAnnotate = \a x -> if a == Any True then map toUpper x else x }
--
-- >>> r $ text "hello" <$$> annotate (Any True) (text "world")
-- hello
-- WORLD
--
annotate :: forall a. (Layout d, Monoid a) => a -> d a -> d a
renderWith :: (Monoid r, Annotation a) => Options a r -> ODoc a -> r
data Options a r
Options :: !Int -> (a -> String -> r) -> Options a r
-- | maximum page width
[optsPageWidth] :: Options a r -> !Int
-- | how to annotate the string. Note: the annotation should
-- preserve the visible length of the string.
[optsAnnotate] :: Options a r -> a -> String -> r
groupingBy :: Monoid a => String -> [(Int, Doc a)] -> Doc a
type Doc = ODoc
-- | The document (x $$> y) concatenates document x
-- and y with a linebreak in between. (infixr 5)
($$) :: (Layout d, Monoid a, Semigroup (d a)) => d a -> d a -> d a
instance Data.Traversable.Traversable Text.PrettyPrint.Compact.Core.AS
instance Data.Foldable.Foldable Text.PrettyPrint.Compact.Core.AS
instance GHC.Base.Functor Text.PrettyPrint.Compact.Core.AS
instance GHC.Show.Show a => GHC.Show.Show (Text.PrettyPrint.Compact.Core.AS a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Text.PrettyPrint.Compact.Core.AS a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.PrettyPrint.Compact.Core.AS a)
instance Data.Traversable.Traversable Text.PrettyPrint.Compact.Core.L
instance Data.Foldable.Foldable Text.PrettyPrint.Compact.Core.L
instance GHC.Base.Functor Text.PrettyPrint.Compact.Core.L
instance GHC.Show.Show a => GHC.Show.Show (Text.PrettyPrint.Compact.Core.L a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Text.PrettyPrint.Compact.Core.L a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.PrettyPrint.Compact.Core.L a)
instance Data.Traversable.Traversable Text.PrettyPrint.Compact.Core.M
instance Data.Foldable.Foldable Text.PrettyPrint.Compact.Core.M
instance GHC.Base.Functor Text.PrettyPrint.Compact.Core.M
instance GHC.Classes.Ord (Text.PrettyPrint.Compact.Core.M a)
instance GHC.Classes.Eq (Text.PrettyPrint.Compact.Core.M a)
instance GHC.Show.Show (Text.PrettyPrint.Compact.Core.M a)
instance (Data.Traversable.Traversable f, Data.Traversable.Traversable g) => Data.Traversable.Traversable (Text.PrettyPrint.Compact.Core.Pair f g)
instance (Data.Foldable.Foldable f, Data.Foldable.Foldable g) => Data.Foldable.Foldable (Text.PrettyPrint.Compact.Core.Pair f g)
instance (GHC.Base.Functor f, GHC.Base.Functor g) => GHC.Base.Functor (Text.PrettyPrint.Compact.Core.Pair f g)
instance GHC.Base.Functor Text.PrettyPrint.Compact.Core.ODoc
instance GHC.Base.Monoid a => Data.String.IsString (Text.PrettyPrint.Compact.Core.Doc a)
instance GHC.Base.Monoid a => GHC.Base.Semigroup (Text.PrettyPrint.Compact.Core.ODoc a)
instance GHC.Base.Monoid a => GHC.Base.Monoid (Text.PrettyPrint.Compact.Core.ODoc a)
instance Text.PrettyPrint.Compact.Core.Layout Text.PrettyPrint.Compact.Core.ODoc
instance (GHC.Base.Semigroup (f a), GHC.Base.Semigroup (g a)) => GHC.Base.Semigroup (Text.PrettyPrint.Compact.Core.Pair f g a)
instance (GHC.Base.Monoid (f a), GHC.Base.Monoid (g a)) => GHC.Base.Monoid (Text.PrettyPrint.Compact.Core.Pair f g a)
instance (Text.PrettyPrint.Compact.Core.Layout a, Text.PrettyPrint.Compact.Core.Layout b) => Text.PrettyPrint.Compact.Core.Layout (Text.PrettyPrint.Compact.Core.Pair a b)
instance Text.PrettyPrint.Compact.Core.Poset (Text.PrettyPrint.Compact.Core.M a)
instance GHC.Base.Semigroup (Text.PrettyPrint.Compact.Core.M a)
instance GHC.Base.Monoid a => GHC.Base.Monoid (Text.PrettyPrint.Compact.Core.M a)
instance Text.PrettyPrint.Compact.Core.Layout Text.PrettyPrint.Compact.Core.M
instance Text.PrettyPrint.Compact.Core.Layout Text.PrettyPrint.Compact.Core.L
instance GHC.Base.Monoid a => GHC.Base.Semigroup (Text.PrettyPrint.Compact.Core.L a)
instance GHC.Base.Monoid a => GHC.Base.Monoid (Text.PrettyPrint.Compact.Core.L a)
instance GHC.Base.Semigroup (Text.PrettyPrint.Compact.Core.AS a)
-- | Compact pretty-printer.
--
--
-- >>> data SExpr = SExpr [SExpr] | Atom String deriving Show
--
-- >>> let pretty :: SExpr -> Doc (); pretty (Atom s) = text s; pretty (SExpr xs) = text "(" <> (sep $ map pretty xs) <> text ")"
--
--
-- Using the above representation, the S-Expression (a b c d)
-- has the following encoding:
--
-- -- >>> let abcd = SExpr [Atom "a",Atom "b",Atom "c",Atom "d"] ---- -- The legible layouts of the abcd S-Expression defined above -- would be either -- --
-- >>> putStrLn $ render $ pretty abcd -- (a b c d) ---- -- or -- --
-- >>> putStrLn $ renderWith defaultOptions { optsPageWidth = 5 } $ pretty abcd
-- (a
-- b
-- c
-- d)
--
--
-- The testData S-Expression is specially crafted to demonstrate
-- general shortcomings of both Hughes and Wadler libraries.
--
-- -- >>> let abcd4 = SExpr [abcd,abcd,abcd,abcd] -- -- >>> let testData = SExpr [ SExpr [Atom "abcde", abcd4], SExpr [Atom "abcdefgh", abcd4]] -- -- >>> putStrLn $ render $ pretty testData -- ((abcde ((a b c d) (a b c d) (a b c d) (a b c d))) -- (abcdefgh ((a b c d) (a b c d) (a b c d) (a b c d)))) ---- -- on 20-column-wide page -- --
-- >>> putStrLn $ renderWith defaultOptions { optsPageWidth = 20 } $ pretty testData
-- ((abcde ((a b c d)
-- (a b c d)
-- (a b c d)
-- (a b c d)))
-- (abcdefgh
-- ((a b c d)
-- (a b c d)
-- (a b c d)
-- (a b c d))))
--
--
-- Yet, neither Hughes' nor Wadler's library can deliver those results.
--
--
-- >>> let pretty' :: SExpr -> Doc Any; pretty' (Atom s) = text s; pretty' (SExpr []) = text "()"; pretty' (SExpr (x:xs)) = text "(" <> (sep $ annotate (Any True) (pretty' x) : map pretty' xs) <> text ")"
--
-- >>> let render' = renderWith defaultOptions { optsAnnotate = \a x -> if a == Any True then map toUpper x else x }
--
-- >>> putStrLn $ render' $ pretty' testData
-- ((ABCDE ((A B C D) (A B C D) (A B C D) (A B C D)))
-- (ABCDEFGH ((A B C D) (A b c d) (A b c d) (A b c d))))
--
module Text.PrettyPrint.Compact
type Doc = ODoc
text :: (Layout d, Monoid a) => String -> d a
flush :: (Layout d, Monoid a) => d a -> d a
char :: Annotation a => Char -> Doc a
-- | The hang combinator implements hanging indentation. The document
-- (hang i x y) either x and y concatenated
-- with <+> or y below x with an
-- additional indentation of i.
hang :: Annotation a => Int -> Doc a -> Doc a -> Doc a
-- | The hang combinator implements hanging indentation. The document
-- (hang separator i x y) either x and y
-- concatenated with <> text separator <> or
-- y below x with an additional indentation of
-- i.
hangWith :: Annotation a => String -> Int -> Doc a -> Doc a -> Doc a
-- | The document (enclosure l r sep xs) concatenates the
-- documents xs separated by sep and encloses the
-- resulting document by l and r. The documents are
-- rendered horizontally if that fits the page. Otherwise they are
-- aligned vertically. All separators are put in front of the elements.
-- For example, the combinator list can be defined with
-- enclosure:
--
-- -- list xs = enclosure lbracket rbracket comma xs -- test = text "list" <+> (list (map int [10,200,3000])) ---- -- Which is layed out with a page width of 20 as: -- --
-- list [10,200,3000] ---- -- But when the page width is 15, it is layed out as: -- --
-- list [10 -- ,200 -- ,3000] --encloseSep :: Annotation a => Doc a -> Doc a -> Doc a -> [Doc a] -> Doc a -- | The document (list xs) comma separates the documents -- xs and encloses them in square brackets. The documents are -- rendered horizontally if that fits the page. Otherwise they are -- aligned vertically. All comma separators are put in front of the -- elements. list :: Annotation a => [Doc a] -> Doc a -- | The document (tupled xs) comma separates the documents -- xs and encloses them in parenthesis. The documents are -- rendered horizontally if that fits the page. Otherwise they are -- aligned vertically. All comma separators are put in front of the -- elements. tupled :: Annotation a => [Doc a] -> Doc a -- | The document (semiBraces xs) separates the documents -- xs with semi colons and encloses them in braces. The -- documents are rendered horizontally if that fits the page. Otherwise -- they are aligned vertically. All semi colons are put in front of the -- elements. semiBraces :: Annotation a => [Doc a] -> Doc a -- | The document (x <+> y) concatenates document x -- and y with a space in between. (infixr 6) (<+>) :: Annotation a => Doc a -> Doc a -> Doc a -- | The document (x $$> y) concatenates document x -- and y with a linebreak in between. (infixr 5) ($$) :: (Layout d, Monoid a, Semigroup (d a)) => d a -> d a -> d a -- | The document (x </> y) puts x and y -- either next to each other (with a space in between) or -- underneath each other. (infixr 5) (>) :: Annotation a => Doc a -> Doc a -> Doc a -- | The document (x <//> y) puts x and y -- either right next to each other (if x fits on a single line) -- or underneath each other. (infixr 5) (/>) :: Annotation a => Doc a -> Doc a -> Doc a -- | The document (x <$$> y) concatenates document -- x and y with a linebreak in between. (infixr 5) (<$$>) :: Annotation a => Doc a -> Doc a -> Doc a -- | The document (hsep xs) concatenates all documents xs -- horizontally with (<+>). hsep :: Annotation a => [Doc a] -> Doc a -- | The document (sep xs) concatenates all documents xs -- either horizontally with (<+>), if it fits the page, or -- vertically with (<$$>). Documents on the left of -- horizontal concatenation must fit on a single line. sep :: Annotation a => [Doc a] -> Doc a -- | The document (hcat xs) concatenates all documents xs -- horizontally with (<>). hcat :: Annotation a => [Doc a] -> Doc a -- | The document (vcat xs) concatenates all documents xs -- vertically with ($$). vcat :: Annotation a => [Doc a] -> Doc a -- | The document (cat xs) concatenates all documents xs -- either horizontally with (<>), if it fits the page, or -- vertically with (<$$>). cat :: Annotation a => [Doc a] -> Doc a -- | (punctuate p xs) concatenates all documents in xs -- with document p except for the last document. -- --
-- someText = map text ["words","in","a","tuple"] -- test = parens (align (cat (punctuate comma someText))) ---- -- This is layed out on a page width of 20 as: -- --
-- (words,in,a,tuple) ---- -- But when the page width is 15, it is layed out as: -- --
-- (words, -- in, -- a, -- tuple) ---- -- (If you want put the commas in front of their elements instead of at -- the end, you should use tupled or, in general, -- encloseSep.) punctuate :: Annotation a => Doc a -> [Doc a] -> [Doc a] -- | The document (enclose l r x) encloses document x -- between documents l and r using (<>). enclose :: Annotation a => Doc a -> Doc a -> Doc a -> Doc a -- | Document (squotes x) encloses document x with single -- quotes "'". squotes :: Annotation a => Doc a -> Doc a -- | Document (dquotes x) encloses document x with double -- quotes '"'. dquotes :: Annotation a => Doc a -> Doc a -- | Document (parens x) encloses document x in -- parenthesis, "(" and ")". parens :: Annotation a => Doc a -> Doc a -- | Document (angles x) encloses document x in angles, -- "<" and ">". angles :: Annotation a => Doc a -> Doc a -- | Document (braces x) encloses document x in braces, -- "{" and "}". braces :: Annotation a => Doc a -> Doc a -- | Document (brackets x) encloses document x in square -- brackets, "[" and "]". brackets :: Annotation a => Doc a -> Doc a -- | The document lparen contains a left parenthesis, "(". lparen :: Annotation a => Doc a -- | The document rparen contains a right parenthesis, ")". rparen :: Annotation a => Doc a -- | The document langle contains a left angle, "<". langle :: Annotation a => Doc a -- | The document rangle contains a right angle, ">". rangle :: Annotation a => Doc a -- | The document lbrace contains a left brace, "{". lbrace :: Annotation a => Doc a -- | The document rbrace contains a right brace, "}". rbrace :: Annotation a => Doc a -- | The document lbracket contains a left square bracket, "[". lbracket :: Annotation a => Doc a -- | The document rbracket contains a right square bracket, "]". rbracket :: Annotation a => Doc a -- | The document squote contains a single quote, "'". squote :: Annotation a => Doc a -- | The document dquote contains a double quote, '"'. dquote :: Annotation a => Doc a -- | The document semi contains a semi colon, ";". semi :: Annotation a => Doc a -- | The document colon contains a colon, ":". colon :: Annotation a => Doc a -- | The document comma contains a comma, ",". comma :: Annotation a => Doc a space :: Annotation a => Doc a -- | The document dot contains a single dot, ".". dot :: Annotation a => Doc a -- | The document backslash contains a back slash, "\". backslash :: Annotation a => Doc a -- | The document equals contains an equal sign, "=". equals :: Annotation a => Doc a -- | The document (string s) concatenates all characters in -- s using line for newline characters and -- char for all other characters. It is used instead of -- text whenever the text contains newline characters. string :: Annotation a => String -> Doc a -- | The document (int i) shows the literal integer i -- using text. int :: Annotation a => Int -> Doc a -- | The document (integer i) shows the literal integer i -- using text. integer :: Annotation a => Integer -> Doc a -- | The document (float f) shows the literal float f -- using text. float :: Annotation a => Float -> Doc a -- | The document (double d) shows the literal double d -- using text. double :: Annotation a => Double -> Doc a -- | The document (rational r) shows the literal rational -- r using text. rational :: Annotation a => Rational -> Doc a bool :: Annotation a => Bool -> Doc a renderWith :: (Monoid r, Annotation a) => Options a r -> ODoc a -> r -- | Render the Doc into String omitting all annotations. render :: Annotation a => Doc a -> String data Options a r Options :: !Int -> (a -> String -> r) -> Options a r -- | maximum page width [optsPageWidth] :: Options a r -> !Int -- | how to annotate the string. Note: the annotation should -- preserve the visible length of the string. [optsAnnotate] :: Options a r -> a -> String -> r defaultOptions :: Options a String -- | <> new annotation to the Doc. -- -- Example: 'Any True' annotation will transform the rendered Doc -- into uppercase: -- --
-- >>> let r = putStrLn . renderWith defaultOptions { optsAnnotate = \a x -> if a == Any True then map toUpper x else x }
--
-- >>> r $ text "hello" <$$> annotate (Any True) (text "world")
-- hello
-- WORLD
--
annotate :: forall a. (Layout d, Monoid a) => a -> d a -> d a