prettyprinter-ansi-terminal 1.1.1.2 → 1.1.2
raw patch · 8 files changed
+618/−368 lines, 8 filesdep +QuickCheckdep +base-compatdep +containersdep ~basedep ~prettyprinterdep ~textnew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: QuickCheck, base-compat, containers, deepseq, gauge, prettyprinter-ansi-terminal
Dependency ranges changed: base, prettyprinter, text
API changes (from Hackage documentation)
- Data.Text.Prettyprint.Doc.Render.Terminal: Black :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Blue :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Bold :: Bold
- Data.Text.Prettyprint.Doc.Render.Terminal: Cyan :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Dull :: Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal: Green :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Italicized :: Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal: Magenta :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Red :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Underlined :: Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal: Vivid :: Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal: White :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: Yellow :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal: bgColor :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: bgColorDull :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: bold :: AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: color :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: colorDull :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: data AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: data Bold
- Data.Text.Prettyprint.Doc.Render.Terminal: data Color
- Data.Text.Prettyprint.Doc.Render.Terminal: data Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal: data Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal: data Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal: hPutDoc :: Handle -> Doc AnsiStyle -> IO ()
- Data.Text.Prettyprint.Doc.Render.Terminal: italicized :: AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal: putDoc :: Doc AnsiStyle -> IO ()
- Data.Text.Prettyprint.Doc.Render.Terminal: renderIO :: Handle -> SimpleDocStream AnsiStyle -> IO ()
- Data.Text.Prettyprint.Doc.Render.Terminal: renderLazy :: SimpleDocStream AnsiStyle -> Text
- Data.Text.Prettyprint.Doc.Render.Terminal: renderStrict :: SimpleDocStream AnsiStyle -> Text
- Data.Text.Prettyprint.Doc.Render.Terminal: underlined :: AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Background :: Layer
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Black :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Blue :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Bold :: Bold
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Cyan :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Dull :: Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Foreground :: Layer
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Green :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Italicized :: Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Magenta :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Red :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: SetAnsiStyle :: Maybe (Intensity, Color) -> Maybe (Intensity, Color) -> Maybe Bold -> Maybe Italicized -> Maybe Underlined -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Underlined :: Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Vivid :: Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: White :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: Yellow :: Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: [ansiBackground] :: AnsiStyle -> Maybe (Intensity, Color)
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: [ansiBold] :: AnsiStyle -> Maybe Bold
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: [ansiForeground] :: AnsiStyle -> Maybe (Intensity, Color)
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: [ansiItalics] :: AnsiStyle -> Maybe Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: [ansiUnderlining] :: AnsiStyle -> Maybe Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: bgColor :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: bgColorDull :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: bold :: AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: color :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: colorDull :: Color -> AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data Bold
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data Layer
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: data Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: hPutDoc :: Handle -> Doc AnsiStyle -> IO ()
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance Data.Semigroup.Semigroup Data.Text.Prettyprint.Doc.Render.Terminal.Internal.AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Base.Monoid Data.Text.Prettyprint.Doc.Render.Terminal.Internal.AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Bold
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Layer
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Eq Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Bold
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Layer
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Classes.Ord Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Bold
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Color
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Intensity
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Italicized
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Layer
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: instance GHC.Show.Show Data.Text.Prettyprint.Doc.Render.Terminal.Internal.Underlined
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: italicized :: AnsiStyle
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: panicStyleStackFullyConsumed :: void
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: panicStyleStackNotFullyConsumed :: Int -> void
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: putDoc :: Doc AnsiStyle -> IO ()
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: renderIO :: Handle -> SimpleDocStream AnsiStyle -> IO ()
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: renderLazy :: SimpleDocStream AnsiStyle -> Text
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: renderStrict :: SimpleDocStream AnsiStyle -> Text
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: styleToRawText :: AnsiStyle -> Text
- Data.Text.Prettyprint.Doc.Render.Terminal.Internal: underlined :: AnsiStyle
+ Prettyprinter.Render.Terminal: Black :: Color
+ Prettyprinter.Render.Terminal: Blue :: Color
+ Prettyprinter.Render.Terminal: Bold :: Bold
+ Prettyprinter.Render.Terminal: Cyan :: Color
+ Prettyprinter.Render.Terminal: Dull :: Intensity
+ Prettyprinter.Render.Terminal: Green :: Color
+ Prettyprinter.Render.Terminal: Italicized :: Italicized
+ Prettyprinter.Render.Terminal: Magenta :: Color
+ Prettyprinter.Render.Terminal: Red :: Color
+ Prettyprinter.Render.Terminal: Underlined :: Underlined
+ Prettyprinter.Render.Terminal: Vivid :: Intensity
+ Prettyprinter.Render.Terminal: White :: Color
+ Prettyprinter.Render.Terminal: Yellow :: Color
+ Prettyprinter.Render.Terminal: bgColor :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal: bgColorDull :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal: bold :: AnsiStyle
+ Prettyprinter.Render.Terminal: color :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal: colorDull :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal: data AnsiStyle
+ Prettyprinter.Render.Terminal: data Bold
+ Prettyprinter.Render.Terminal: data Color
+ Prettyprinter.Render.Terminal: data Intensity
+ Prettyprinter.Render.Terminal: data Italicized
+ Prettyprinter.Render.Terminal: data Underlined
+ Prettyprinter.Render.Terminal: hPutDoc :: Handle -> Doc AnsiStyle -> IO ()
+ Prettyprinter.Render.Terminal: italicized :: AnsiStyle
+ Prettyprinter.Render.Terminal: putDoc :: Doc AnsiStyle -> IO ()
+ Prettyprinter.Render.Terminal: renderIO :: Handle -> SimpleDocStream AnsiStyle -> IO ()
+ Prettyprinter.Render.Terminal: renderLazy :: SimpleDocStream AnsiStyle -> Text
+ Prettyprinter.Render.Terminal: renderStrict :: SimpleDocStream AnsiStyle -> Text
+ Prettyprinter.Render.Terminal: underlined :: AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: Black :: Color
+ Prettyprinter.Render.Terminal.Internal: Blue :: Color
+ Prettyprinter.Render.Terminal.Internal: Bold :: Bold
+ Prettyprinter.Render.Terminal.Internal: Cyan :: Color
+ Prettyprinter.Render.Terminal.Internal: Dull :: Intensity
+ Prettyprinter.Render.Terminal.Internal: Green :: Color
+ Prettyprinter.Render.Terminal.Internal: Italicized :: Italicized
+ Prettyprinter.Render.Terminal.Internal: Magenta :: Color
+ Prettyprinter.Render.Terminal.Internal: Red :: Color
+ Prettyprinter.Render.Terminal.Internal: SetAnsiStyle :: Maybe (Intensity, Color) -> Maybe (Intensity, Color) -> Maybe Bold -> Maybe Italicized -> Maybe Underlined -> AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: Underlined :: Underlined
+ Prettyprinter.Render.Terminal.Internal: Vivid :: Intensity
+ Prettyprinter.Render.Terminal.Internal: White :: Color
+ Prettyprinter.Render.Terminal.Internal: Yellow :: Color
+ Prettyprinter.Render.Terminal.Internal: [ansiBackground] :: AnsiStyle -> Maybe (Intensity, Color)
+ Prettyprinter.Render.Terminal.Internal: [ansiBold] :: AnsiStyle -> Maybe Bold
+ Prettyprinter.Render.Terminal.Internal: [ansiForeground] :: AnsiStyle -> Maybe (Intensity, Color)
+ Prettyprinter.Render.Terminal.Internal: [ansiItalics] :: AnsiStyle -> Maybe Italicized
+ Prettyprinter.Render.Terminal.Internal: [ansiUnderlining] :: AnsiStyle -> Maybe Underlined
+ Prettyprinter.Render.Terminal.Internal: bgColor :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: bgColorDull :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: bold :: AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: color :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: colorDull :: Color -> AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: data AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: data Bold
+ Prettyprinter.Render.Terminal.Internal: data Color
+ Prettyprinter.Render.Terminal.Internal: data Intensity
+ Prettyprinter.Render.Terminal.Internal: data Italicized
+ Prettyprinter.Render.Terminal.Internal: data Underlined
+ Prettyprinter.Render.Terminal.Internal: hPutDoc :: Handle -> Doc AnsiStyle -> IO ()
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Base.Monoid Prettyprinter.Render.Terminal.Internal.AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Base.Semigroup Prettyprinter.Render.Terminal.Internal.AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.Bold
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.Color
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.Intensity
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.Italicized
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.Layer
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Eq Prettyprinter.Render.Terminal.Internal.Underlined
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.Bold
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.Color
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.Intensity
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.Italicized
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.Layer
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Classes.Ord Prettyprinter.Render.Terminal.Internal.Underlined
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.Bold
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.Color
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.Intensity
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.Italicized
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.Layer
+ Prettyprinter.Render.Terminal.Internal: instance GHC.Show.Show Prettyprinter.Render.Terminal.Internal.Underlined
+ Prettyprinter.Render.Terminal.Internal: italicized :: AnsiStyle
+ Prettyprinter.Render.Terminal.Internal: putDoc :: Doc AnsiStyle -> IO ()
+ Prettyprinter.Render.Terminal.Internal: renderIO :: Handle -> SimpleDocStream AnsiStyle -> IO ()
+ Prettyprinter.Render.Terminal.Internal: renderLazy :: SimpleDocStream AnsiStyle -> Text
+ Prettyprinter.Render.Terminal.Internal: renderStrict :: SimpleDocStream AnsiStyle -> Text
+ Prettyprinter.Render.Terminal.Internal: underlined :: AnsiStyle
Files
- CHANGELOG.md +14/−0
- bench/LargeOutput.hs +159/−0
- misc/version-compatibility-macros.h +5/−1
- prettyprinter-ansi-terminal.cabal +30/−6
- src/Data/Text/Prettyprint/Doc/Render/Terminal.hs +10/−32
- src/Data/Text/Prettyprint/Doc/Render/Terminal/Internal.hs +9/−329
- src/Prettyprinter/Render/Terminal.hs +35/−0
- src/Prettyprinter/Render/Terminal/Internal.hs +356/−0
CHANGELOG.md view
@@ -1,3 +1,17 @@+# [1.1.2]++- [Add shallower `Prettyprinter` module hierarchy exposing the same API.](https://github.com/quchen/prettyprinter/pull/174)+ * The current plan for the existing `Data.Text.Prettyprint.Doc*` modules is:+ * Start deprecation in early 2021.+ * Remove the modules after a deprecation period of at least one year.+- [Make `renderLazy` lazy, and speed it up.](https://github.com/quchen/prettyprinter/pull/176)+- [Add export list for Prettyprinter.Render.Terminal.Internal.](https://github.com/quchen/prettyprinter/pull/148)+- [Optimize generating spaces for indentation.](https://github.com/quchen/prettyprinter/pull/132)+- [Enable `-O2`.](https://github.com/quchen/prettyprinter/pull/144)+- [Extend GHC support to 7.6 and 7.4.](https://github.com/quchen/prettyprinter/pull/74)++[1.1.2]: https://github.com/quchen/prettyprinter/compare/ansi-terminal-v1.1.1.2...ansi-terminal-v1.1.2+ # 1.1.1.2 - Fix documentation claiming there would be a trailing newline in `renderIO`
+ bench/LargeOutput.hs view
@@ -0,0 +1,159 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++-- | This benchmark is derived from the large-output benchmark in prettyprinter, but contains additional annotations.+module Main (main) where++import Prelude ()+import Prelude.Compat++import Control.DeepSeq+import Control.Monad.Compat+import Data.Char+import Data.Map (Map)+import qualified Data.Map as M+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.IO as T+import qualified Data.Text.Lazy as TL+import Gauge+import GHC.Generics+import Prettyprinter+import Prettyprinter.Render.Terminal as Terminal+import qualified Prettyprinter.Render.Text as Text+import Test.QuickCheck+import Test.QuickCheck.Gen+import Test.QuickCheck.Random++++newtype Program = Program Binds deriving (Show, Generic)+newtype Binds = Binds (Map Text LambdaForm) deriving (Show, Generic)+data LambdaForm = LambdaForm ![Text] ![Text] !Expr deriving (Show, Generic)+data Expr+ = Let Binds Expr+ | Case Expr [Alt]+ | AppF Text [Text]+ | AppC Text [Text]+ | AppP Text Text Text+ | LitE Int+ deriving (Show, Generic)+data Alt = Alt Text [Text] Expr deriving (Show, Generic)++instance NFData Program+instance NFData Binds+instance NFData LambdaForm+instance NFData Expr+instance NFData Alt++instance Arbitrary Program where arbitrary = fmap Program arbitrary+instance Arbitrary Binds where+ arbitrary = do+ NonEmpty xs <- arbitrary+ pure (Binds (M.fromList xs))+instance Arbitrary LambdaForm where+ arbitrary = LambdaForm <$> fromTo 0 2 arbitrary <*> fromTo 0 2 arbitrary <*> arbitrary++instance Arbitrary Expr where+ arbitrary = (oneof . map scaled)+ [ Let <$> arbitrary <*> arbitrary+ , Case <$> arbitrary <*> (do NonEmpty xs <- arbitrary; pure xs)+ , AppF <$> arbitrary <*> fromTo 0 3 arbitrary+ , AppC <$> ucFirst arbitrary <*> fromTo 0 3 arbitrary+ , AppP <$> arbitrary <*> arbitrary <*> arbitrary+ , LitE <$> arbitrary ]+instance Arbitrary Alt where arbitrary = Alt <$> ucFirst arbitrary <*> fromTo 0 3 arbitrary <*> arbitrary+instance Arbitrary Text where+ arbitrary = do+ n <- choose (3,6)+ str <- replicateM n (elements ['a'..'z'])+ if str `elem` ["let", "in", "case", "of"]+ then arbitrary+ else pure (T.pack str)++ucFirst :: Gen Text -> Gen Text+ucFirst gen = do+ x <- gen+ case T.uncons x of+ Nothing -> pure x+ Just (t,ext) -> pure (T.cons (toUpper t) ext)++anCol :: Color -> Doc AnsiStyle -> Doc AnsiStyle+anCol = annotate . color++prettyProgram :: Program -> Doc AnsiStyle+prettyProgram (Program binds) = annotate italicized $ prettyBinds binds++prettyBinds :: Binds -> Doc AnsiStyle+prettyBinds (Binds bs) = align (vsep (map prettyBinding (M.assocs bs)))+ where+ prettyBinding (var, lambda) = pretty var <+> anCol Red "=" <+> prettyLambdaForm lambda++prettyLambdaForm :: LambdaForm -> Doc AnsiStyle+prettyLambdaForm (LambdaForm free bound body) = prettyExp . (<+> anCol Blue "->") . prettyBound . prettyFree $ anCol Blue "\\"+ where+ prettyFree | null free = id+ | otherwise = (<> anCol Blue lparen <> hsep (map pretty free) <> anCol Blue rparen)+ prettyBound | null bound = id+ | null free = (<> hsep (map pretty bound))+ | otherwise = (<+> hsep (map pretty bound))+ prettyExp = (<+> prettyExpr body)++prettyExpr :: Expr -> Doc AnsiStyle+prettyExpr = \case+ Let binds body ->+ align (vsep [ anCol Red "let" <+> align (prettyBinds binds)+ , anCol Red "in" <+> prettyExpr body ])++ Case scrutinee alts -> vsep+ [ anCol Yellow "case" <+> prettyExpr scrutinee <+> anCol Yellow "of"+ , indent 4 (align (vsep (map prettyAlt alts))) ]++ AppF f [] -> annotate bold . anCol Green $ pretty f+ AppF f args -> annotate bold . anCol Green $ pretty f <+> hsep (map pretty args)++ AppC c [] -> annotate bold . anCol Green $ pretty c+ AppC c args -> annotate bold . anCol Green $ pretty c <+> hsep (map pretty args)++ AppP op x y -> annotate bold . anCol Green $ pretty op <+> pretty x <+> pretty y++ LitE lit -> annotate bold . anCol Green $ pretty lit++prettyAlt :: Alt -> Doc AnsiStyle+prettyAlt (Alt con [] body) = pretty con <+> anCol Yellow "->" <+> prettyExpr body+prettyAlt (Alt con args body) = pretty con <+> hsep (map pretty args) <+> anCol Yellow "->" <+> prettyExpr body++scaled :: Gen a -> Gen a+scaled = scale (\n -> n * 2 `quot` 3)++fromTo :: Int -> Int -> Gen b -> Gen b+fromTo a b gen = do+ n <- choose (min a b, max a b)+ resize n gen++randomProgram+ :: Int -- ^ Seed+ -> Int -- ^ Generator size+ -> Program+randomProgram seed size = let MkGen gen = arbitrary in gen (mkQCGen seed) size++main :: IO ()+main = do+ let prog = randomProgram 1 60+ layoutOpts = defaultLayoutOptions { layoutPageWidth = Unbounded }+ renderedProg = (renderLazy . layoutPretty layoutOpts . prettyProgram) prog+ (progLines, progWidth) = let l = TL.lines renderedProg in (length l, maximum (map TL.length l))+ putDoc ("Program size:" <+> pretty progLines <+> "lines, maximum width:" <+> pretty progWidth)++ let render :: (SimpleDocStream AnsiStyle -> TL.Text) -> Program -> TL.Text+ render r = r . layoutPretty layoutOpts . prettyProgram++ rnf prog `seq` T.putStrLn "Starting benchmark…"++ defaultMain+ [ bench "prettyprinter-ansi-terminal" $ nf (render Terminal.renderLazy) prog+ , bench "prettyprinter" $ nf (render Text.renderLazy) prog+ ]
misc/version-compatibility-macros.h view
@@ -10,10 +10,14 @@ #define APPLICATIVE_MONAD MIN_VERSION_base(4,8,0) #define FOLDABLE_TRAVERSABLE_IN_PRELUDE MIN_VERSION_base(4,8,0)+#define FUNCTOR_IDENTITY_IN_BASE MIN_VERSION_base(4,8,0) #define MONOID_IN_PRELUDE MIN_VERSION_base(4,8,0) #define NATURAL_IN_BASE MIN_VERSION_base(4,8,0) #define SEMIGROUP_IN_BASE MIN_VERSION_base(4,9,0)-#define MONAD_FAIL MIN_VERSION_base(4,9,0)++#define SEMIGROUP_MONOID_SUPERCLASS MIN_VERSION_base(4,11,0)++#define FAIL_IN_MONAD !(MIN_VERSION_base(4,13,0)) #endif
prettyprinter-ansi-terminal.cabal view
@@ -1,5 +1,5 @@ name: prettyprinter-ansi-terminal-version: 1.1.1.2+version: 1.1.2 cabal-version: >= 1.10 category: User Interfaces, Text synopsis: ANSI terminal backend for the »prettyprinter« package.@@ -10,11 +10,16 @@ , misc/version-compatibility-macros.h , CHANGELOG.md author: David Luposchainsky-maintainer: David Luposchainsky <dluposchainsky at google>+maintainer: Simon Jakobi <simon.jakobi@gmail.com>, David Luposchainsky <dluposchainsky at google> bug-reports: http://github.com/quchen/prettyprinter/issues homepage: http://github.com/quchen/prettyprinter build-type: Simple-tested-with: GHC==7.8.4, GHC==7.10.2, GHC==7.10.3, GHC==8.0.1, GHC==8.0.2+tested-with: GHC == 7.8.4+ , GHC == 7.10.2+ , GHC == 7.10.3+ , GHC == 8.0.1+ , GHC == 8.0.2+ , GHC == 8.2.2 source-repository head type: git@@ -23,18 +28,19 @@ library exposed-modules: Data.Text.Prettyprint.Doc.Render.Terminal , Data.Text.Prettyprint.Doc.Render.Terminal.Internal- ghc-options: -Wall+ , Prettyprinter.Render.Terminal+ , Prettyprinter.Render.Terminal.Internal+ ghc-options: -Wall -O2 hs-source-dirs: src include-dirs: misc default-language: Haskell2010 other-extensions: CPP- , LambdaCase , OverloadedStrings build-depends:- base >= 4.7 && < 5+ base >= 4.5 && < 5 , ansi-terminal >= 0.4.0 , text >= 1.2 , prettyprinter >= 1.1.1@@ -56,3 +62,21 @@ if impl (ghc < 7.10) buildable: False -- Doctest cannot search folders in old versions it seems :-(++benchmark large-output+ build-depends:+ base >= 4.5 && < 5+ , base-compat >=0.9.3 && <0.12+ , containers+ , deepseq+ , gauge >= 0.2+ , prettyprinter+ , prettyprinter-ansi-terminal+ , QuickCheck >= 2.7+ , text++ hs-source-dirs: bench+ main-is: LargeOutput.hs+ ghc-options: -O2 -threaded -rtsopts -with-rtsopts=-N -Wall+ default-language: Haskell2010+ type: exitcode-stdio-1.0
src/Data/Text/Prettyprint/Doc/Render/Terminal.hs view
@@ -1,35 +1,13 @@--- | Render 'SimpleDocStream' in a terminal.+-- | This module is part of the old @Data.Text.Prettyprint.Doc@ module hierarchy+-- which is being replaced by a shallower @Prettyprinter@ module hierarchy+-- offering the same API.+--+-- This module will be deprecated and eventually removed.+--+-- Use "Prettyprinter.Render.Terminal" instead. module Data.Text.Prettyprint.Doc.Render.Terminal (- -- * Styling- AnsiStyle,- Color(..),-- -- ** Font color- color, colorDull,-- -- ** Background color- bgColor, bgColorDull,-- -- ** Font style- bold, italicized, underlined,-- -- ** Internal markers- --- -- | These should only be used for writing adaptors to other libraries; for- -- the average use case, use 'bold', 'bgColorDull', etc.- Intensity(..),- Bold(..),- Underlined(..),- Italicized(..),-- -- * Conversion to ANSI-infused 'Text'- renderLazy, renderStrict,-- -- * Render directly to 'stdout'- renderIO,-- -- ** Convenience functions- putDoc, hPutDoc,+ module Prettyprinter.Render.Terminal ) where -import Data.Text.Prettyprint.Doc.Render.Terminal.Internal+import Prettyprinter.Render.Terminal+
src/Data/Text/Prettyprint/Doc/Render/Terminal/Internal.hs view
@@ -1,334 +1,14 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}--#include "version-compatibility-macros.h"---- | __Warning:__ Internal module. May change arbitrarily between versions.-module Data.Text.Prettyprint.Doc.Render.Terminal.Internal where----import Control.Applicative-import Control.Monad.ST-import Data.IORef-import Data.Maybe-import Data.Semigroup-import Data.STRef-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.IO as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Builder as TLB-import qualified System.Console.ANSI as ANSI-import System.IO (Handle, hPutChar, stdout)--import Data.Text.Prettyprint.Doc-import Data.Text.Prettyprint.Doc.Render.Util.Panic------ $setup------ (Definitions for the doctests)------ >>> :set -XOverloadedStrings--- >>> import qualified Data.Text.Lazy.IO as TL--- >>> import qualified Data.Text.Lazy as TL--- >>> import Data.Text.Prettyprint.Doc.Render.Terminal------ | The 8 ANSI terminal colors.-data Color = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White- deriving (Eq, Ord, Show)---- | Dull or vivid coloring, as supported by ANSI terminals.-data Intensity = Vivid | Dull- deriving (Eq, Ord, Show)---- | Foreground (text) or background (paper) color-data Layer = Foreground | Background- deriving (Eq, Ord, Show)--data Bold = Bold deriving (Eq, Ord, Show)-data Underlined = Underlined deriving (Eq, Ord, Show)-data Italicized = Italicized deriving (Eq, Ord, Show)---- | Style the foreground with a vivid color.-color :: Color -> AnsiStyle-color c = mempty { ansiForeground = Just (Vivid, c) }---- | Style the background with a vivid color.-bgColor :: Color -> AnsiStyle-bgColor c = mempty { ansiBackground = Just (Vivid, c) }---- | Style the foreground with a dull color.-colorDull :: Color -> AnsiStyle-colorDull c = mempty { ansiForeground = Just (Dull, c) }---- | Style the background with a dull color.-bgColorDull :: Color -> AnsiStyle-bgColorDull c = mempty { ansiBackground = Just (Dull, c) }---- | Render in __bold__.-bold :: AnsiStyle-bold = mempty { ansiBold = Just Bold }---- | Render in /italics/.-italicized :: AnsiStyle-italicized = mempty { ansiItalics = Just Italicized }---- | Render underlined.-underlined :: AnsiStyle-underlined = mempty { ansiUnderlining = Just Underlined }---- | @('renderLazy' doc)@ takes the output @doc@ from a rendering function--- and transforms it to lazy text, including ANSI styling directives for things--- like colorization.------ ANSI color information will be discarded by this function unless you are--- running on a Unix-like operating system. This is due to a technical--- limitation in Windows ANSI support.------ With a bit of trickery to make the ANSI codes printable, here is an example--- that would render colored in an ANSI terminal:------ >>> let render = TL.putStrLn . TL.replace "\ESC" "\\e" . renderLazy . layoutPretty defaultLayoutOptions--- >>> let doc = annotate (color Red) ("red" <+> align (vsep [annotate (color Blue <> underlined) ("blue+u" <+> annotate bold "bold" <+> "blue+u"), "red"]))--- >>> render (unAnnotate doc)--- red blue+u bold blue+u--- red--- >>> render doc--- \e[0;91mred \e[0;94;4mblue+u \e[0;94;1;4mbold\e[0;94;4m blue+u\e[0;91m--- red\e[0m------ Run the above via @echo -e '...'@ in your terminal to see the coloring.-renderLazy :: SimpleDocStream AnsiStyle -> TL.Text-renderLazy sdoc = runST (do- styleStackRef <- newSTRef [mempty]- outputRef <- newSTRef mempty-- let push x = modifySTRef' styleStackRef (x :)- unsafePeek = readSTRef styleStackRef >>= \case- [] -> panicPeekedEmpty- x:_ -> pure x- unsafePop = readSTRef styleStackRef >>= \case- [] -> panicPeekedEmpty- x:xs -> writeSTRef styleStackRef xs >> pure x- writeOutput x = modifySTRef outputRef (<> x)-- let go = \case- SFail -> panicUncaughtFail- SEmpty -> pure ()- SChar c rest -> do- writeOutput (TLB.singleton c)- go rest- SText _ t rest -> do- writeOutput (TLB.fromText t)- go rest- SLine i rest -> do- writeOutput (TLB.singleton '\n' <> TLB.fromText (T.replicate i " "))- go rest- SAnnPush style rest -> do- currentStyle <- unsafePeek- let newStyle = style <> currentStyle- push newStyle- writeOutput (TLB.fromText (styleToRawText newStyle))- go rest- SAnnPop rest -> do- _currentStyle <- unsafePop- newStyle <- unsafePeek- writeOutput (TLB.fromText (styleToRawText newStyle))- go rest- go sdoc- readSTRef styleStackRef >>= \case- [] -> panicStyleStackFullyConsumed- [_] -> fmap TLB.toLazyText (readSTRef outputRef)- xs -> panicStyleStackNotFullyConsumed (length xs) )---- | @('renderIO' h sdoc)@ writes @sdoc@ to the handle @h@.------ >>> let render = renderIO System.IO.stdout . layoutPretty defaultLayoutOptions--- >>> let doc = annotate (color Red) ("red" <+> align (vsep [annotate (color Blue <> underlined) ("blue+u" <+> annotate bold "bold" <+> "blue+u"), "red"]))------ We render the 'unAnnotate'd version here, since the ANSI codes don’t display--- well in Haddock,------ >>> render (unAnnotate doc)--- red blue+u bold blue+u--- red------ This function behaves just like------ @--- 'renderIO' h sdoc = 'TL.hPutStr' h ('renderLazy' sdoc)--- @------ but will not generate any intermediate text, rendering directly to the--- handle.-renderIO :: Handle -> SimpleDocStream AnsiStyle -> IO ()-renderIO h sdoc = do- styleStackRef <- newIORef [mempty]-- let push x = modifyIORef' styleStackRef (x :)- unsafePeek = readIORef styleStackRef >>= \case- [] -> panicPeekedEmpty- x:_ -> pure x- unsafePop = readIORef styleStackRef >>= \case- [] -> panicPeekedEmpty- x:xs -> writeIORef styleStackRef xs >> pure x-- let go = \case- SFail -> panicUncaughtFail- SEmpty -> pure ()- SChar c rest -> do- hPutChar h c- go rest- SText _ t rest -> do- T.hPutStr h t- go rest- SLine i rest -> do- hPutChar h '\n'- T.hPutStr h (T.replicate i " ")- go rest- SAnnPush style rest -> do- currentStyle <- unsafePeek- let newStyle = style <> currentStyle- push newStyle- T.hPutStr h (styleToRawText newStyle)- go rest- SAnnPop rest -> do- _currentStyle <- unsafePop- newStyle <- unsafePeek- T.hPutStr h (styleToRawText newStyle)- go rest- go sdoc- readIORef styleStackRef >>= \case- [] -> panicStyleStackFullyConsumed- [_] -> pure ()- xs -> panicStyleStackNotFullyConsumed (length xs)--panicStyleStackFullyConsumed :: void-panicStyleStackFullyConsumed- = error ("There is no empty style left at the end of rendering" ++- " (but there should be). Please report this as a bug.")--panicStyleStackNotFullyConsumed :: Int -> void-panicStyleStackNotFullyConsumed len- = error ("There are " <> show len <> " styles left at the" ++- "end of rendering (there should be only 1). Please report" ++- " this as a bug.")---- $--- >>> let render = renderIO System.IO.stdout . layoutPretty defaultLayoutOptions--- >>> let doc = annotate (color Red) ("red" <+> align (vsep [annotate (color Blue <> underlined) ("blue+u" <+> annotate bold "bold" <+> "blue+u"), "red"]))--- >>> render (unAnnotate doc)--- red blue+u bold blue+u--- red------ This test won’t work since I don’t know how to type \ESC for doctest :-/--- -- >>> render doc--- -- \ESC[0;91mred \ESC[0;94;4mblue+u \ESC[0;94;1;4mbold\ESC[0;94;4m blue+u\ESC[0;91m--- -- red\ESC[0m---- | Render the annotated document in a certain style. Styles not set in the--- annotation will use the style of the surrounding document, or the terminal’s--- default if none has been set yet.------ @--- style = 'color' 'Green' '<>' 'bold'--- styledDoc = 'annotate' style "hello world"--- @-data AnsiStyle = SetAnsiStyle- { ansiForeground :: Maybe (Intensity, Color) -- ^ Set the foreground color, or keep the old one.- , ansiBackground :: Maybe (Intensity, Color) -- ^ Set the background color, or keep the old one.- , ansiBold :: Maybe Bold -- ^ Switch on boldness, or don’t do anything.- , ansiItalics :: Maybe Italicized -- ^ Switch on italics, or don’t do anything.- , ansiUnderlining :: Maybe Underlined -- ^ Switch on underlining, or don’t do anything.- } deriving (Eq, Ord, Show)---- | Keep the first decision for each of foreground color, background color,--- boldness, italication, and underlining. If a certain style is not set, the--- terminal’s default will be used.------ Example:+-- | This module is part of the old @Data.Text.Prettyprint.Doc@ module hierarchy+-- which is being replaced by a shallower @Prettyprinter@ module hierarchy+-- offering the same API. ----- @--- 'color' 'Red' '<>' 'color' 'Green'--- @+-- This module will be deprecated and eventually removed. ----- is red because the first color wins, and not bold because (or if) that’s the--- terminal’s default.-instance Semigroup AnsiStyle where- cs1 <> cs2 = SetAnsiStyle- { ansiForeground = ansiForeground cs1 <|> ansiForeground cs2- , ansiBackground = ansiBackground cs1 <|> ansiBackground cs2- , ansiBold = ansiBold cs1 <|> ansiBold cs2- , ansiItalics = ansiItalics cs1 <|> ansiItalics cs2- , ansiUnderlining = ansiUnderlining cs1 <|> ansiUnderlining cs2 }---- | 'mempty' does nothing, which is equivalent to inheriting the style of the--- surrounding doc, or the terminal’s default if no style has been set yet.-instance Monoid AnsiStyle where- mempty = SetAnsiStyle Nothing Nothing Nothing Nothing Nothing- mappend = (<>)--styleToRawText :: AnsiStyle -> Text-styleToRawText = T.pack . ANSI.setSGRCode . stylesToSgrs- where- stylesToSgrs :: AnsiStyle -> [ANSI.SGR]- stylesToSgrs (SetAnsiStyle fg bg b i u) = catMaybes- [ Just ANSI.Reset- , fmap (\(intensity, c) -> ANSI.SetColor ANSI.Foreground (convertIntensity intensity) (convertColor c)) fg- , fmap (\(intensity, c) -> ANSI.SetColor ANSI.Background (convertIntensity intensity) (convertColor c)) bg- , fmap (\_ -> ANSI.SetConsoleIntensity ANSI.BoldIntensity) b- , fmap (\_ -> ANSI.SetItalicized True) i- , fmap (\_ -> ANSI.SetUnderlining ANSI.SingleUnderline) u- ]-- convertIntensity :: Intensity -> ANSI.ColorIntensity- convertIntensity = \case- Vivid -> ANSI.Vivid- Dull -> ANSI.Dull-- convertColor :: Color -> ANSI.Color- convertColor = \case- Black -> ANSI.Black- Red -> ANSI.Red- Green -> ANSI.Green- Yellow -> ANSI.Yellow- Blue -> ANSI.Blue- Magenta -> ANSI.Magenta- Cyan -> ANSI.Cyan- White -> ANSI.White+-- Use "Prettyprinter.Render.Terminal.Internal" instead.+module Data.Text.Prettyprint.Doc.Render.Terminal.Internal (+ module Prettyprinter.Render.Terminal.Internal+) where +import Prettyprinter.Render.Terminal.Internal --- | @('renderStrict' sdoc)@ takes the output @sdoc@ from a rendering and--- transforms it to strict text.-renderStrict :: SimpleDocStream AnsiStyle -> Text-renderStrict = TL.toStrict . renderLazy---- | @('putDoc' doc)@ prettyprints document @doc@ to standard output using--- 'defaultLayoutOptions'.------ >>> putDoc ("hello" <+> "world")--- hello world------ @--- 'putDoc' = 'hPutDoc' 'stdout'--- @-putDoc :: Doc AnsiStyle -> IO ()-putDoc = hPutDoc stdout---- | Like 'putDoc', but instead of using 'stdout', print to a user-provided--- handle, e.g. a file or a socket using 'defaultLayoutOptions'.------ > main = withFile "someFile.txt" (\h -> hPutDoc h (vcat ["vertical", "text"]))------ @--- 'hPutDoc' h doc = 'renderIO' h ('layoutPretty' 'defaultLayoutOptions' doc)--- @-hPutDoc :: Handle -> Doc AnsiStyle -> IO ()-hPutDoc h doc = renderIO h (layoutPretty defaultLayoutOptions doc)
+ src/Prettyprinter/Render/Terminal.hs view
@@ -0,0 +1,35 @@+-- | Render 'SimpleDocStream' in a terminal.+module Prettyprinter.Render.Terminal (+ -- * Styling+ AnsiStyle,+ Color(..),++ -- ** Font color+ color, colorDull,++ -- ** Background color+ bgColor, bgColorDull,++ -- ** Font style+ bold, italicized, underlined,++ -- ** Internal markers+ --+ -- | These should only be used for writing adaptors to other libraries; for+ -- the average use case, use 'bold', 'bgColorDull', etc.+ Intensity(..),+ Bold(..),+ Underlined(..),+ Italicized(..),++ -- * Conversion to ANSI-infused 'Text'+ renderLazy, renderStrict,++ -- * Render directly to 'stdout'+ renderIO,++ -- ** Convenience functions+ putDoc, hPutDoc,+) where++import Prettyprinter.Render.Terminal.Internal
+ src/Prettyprinter/Render/Terminal/Internal.hs view
@@ -0,0 +1,356 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}++{-# OPTIONS_HADDOCK not-home #-}++#include "version-compatibility-macros.h"++-- | __Warning:__ Internal module. May change arbitrarily between versions.+module Prettyprinter.Render.Terminal.Internal (+ -- * Styling+ AnsiStyle(..),+ Color(..),++ -- ** Font color+ color, colorDull,++ -- ** Background color+ bgColor, bgColorDull,++ -- ** Font style+ bold, italicized, underlined,++ -- ** Internal markers+ Intensity(..),+ Bold(..),+ Underlined(..),+ Italicized(..),++ -- * Conversion to ANSI-infused 'Text'+ renderLazy, renderStrict,++ -- * Render directly to 'stdout'+ renderIO,++ -- ** Convenience functions+ putDoc, hPutDoc,+) where++++import Control.Applicative+import Data.IORef+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.IO as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified System.Console.ANSI as ANSI+import System.IO (Handle, hPutChar, stdout)++import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.Util.Panic++#if !(SEMIGROUP_MONOID_SUPERCLASS)+import Data.Semigroup+#endif++#if !(MIN_VERSION_base(4,6,0))+modifyIORef' :: IORef a -> (a -> a) -> IO ()+modifyIORef' ref f = do+ x <- readIORef ref+ let x' = f x+ x' `seq` writeIORef ref x'+#endif++-- $setup+--+-- (Definitions for the doctests)+--+-- >>> :set -XOverloadedStrings+-- >>> import qualified Data.Text.Lazy.IO as TL+-- >>> import qualified Data.Text.Lazy as TL+-- >>> import Prettyprinter.Render.Terminal++++-- | The 8 ANSI terminal colors.+data Color = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White+ deriving (Eq, Ord, Show)++-- | Dull or vivid coloring, as supported by ANSI terminals.+data Intensity = Vivid | Dull+ deriving (Eq, Ord, Show)++-- | Foreground (text) or background (paper) color+data Layer = Foreground | Background+ deriving (Eq, Ord, Show)++data Bold = Bold deriving (Eq, Ord, Show)+data Underlined = Underlined deriving (Eq, Ord, Show)+data Italicized = Italicized deriving (Eq, Ord, Show)++-- | Style the foreground with a vivid color.+color :: Color -> AnsiStyle+color c = mempty { ansiForeground = Just (Vivid, c) }++-- | Style the background with a vivid color.+bgColor :: Color -> AnsiStyle+bgColor c = mempty { ansiBackground = Just (Vivid, c) }++-- | Style the foreground with a dull color.+colorDull :: Color -> AnsiStyle+colorDull c = mempty { ansiForeground = Just (Dull, c) }++-- | Style the background with a dull color.+bgColorDull :: Color -> AnsiStyle+bgColorDull c = mempty { ansiBackground = Just (Dull, c) }++-- | Render in __bold__.+bold :: AnsiStyle+bold = mempty { ansiBold = Just Bold }++-- | Render in /italics/.+italicized :: AnsiStyle+italicized = mempty { ansiItalics = Just Italicized }++-- | Render underlined.+underlined :: AnsiStyle+underlined = mempty { ansiUnderlining = Just Underlined }++-- | @('renderLazy' doc)@ takes the output @doc@ from a rendering function+-- and transforms it to lazy text, including ANSI styling directives for things+-- like colorization.+--+-- ANSI color information will be discarded by this function unless you are+-- running on a Unix-like operating system. This is due to a technical+-- limitation in Windows ANSI support.+--+-- With a bit of trickery to make the ANSI codes printable, here is an example+-- that would render colored in an ANSI terminal:+--+-- >>> let render = TL.putStrLn . TL.replace "\ESC" "\\e" . renderLazy . layoutPretty defaultLayoutOptions+-- >>> let doc = annotate (color Red) ("red" <+> align (vsep [annotate (color Blue <> underlined) ("blue+u" <+> annotate bold "bold" <+> "blue+u"), "red"]))+-- >>> render (unAnnotate doc)+-- red blue+u bold blue+u+-- red+-- >>> render doc+-- \e[0;91mred \e[0;94;4mblue+u \e[0;94;1;4mbold\e[0;94;4m blue+u\e[0;91m+-- red\e[0m+--+-- Run the above via @echo -e '...'@ in your terminal to see the coloring.+renderLazy :: SimpleDocStream AnsiStyle -> TL.Text+renderLazy =+ let push x = (x :)++ unsafePeek [] = panicPeekedEmpty+ unsafePeek (x:_) = x++ unsafePop [] = panicPoppedEmpty+ unsafePop (x:xs) = (x, xs)++ go :: [AnsiStyle] -> SimpleDocStream AnsiStyle -> TLB.Builder+ go s sds = case sds of+ SFail -> panicUncaughtFail+ SEmpty -> mempty+ SChar c rest -> TLB.singleton c <> go s rest+ SText _ t rest -> TLB.fromText t <> go s rest+ SLine i rest -> TLB.singleton '\n' <> TLB.fromText (T.replicate i " ") <> go s rest+ SAnnPush style rest ->+ let currentStyle = unsafePeek s+ newStyle = style <> currentStyle+ in TLB.fromText (styleToRawText newStyle) <> go (push style s) rest+ SAnnPop rest ->+ let (_currentStyle, s') = unsafePop s+ newStyle = unsafePeek s'+ in TLB.fromText (styleToRawText newStyle) <> go s' rest++ in TLB.toLazyText . go [mempty]+++-- | @('renderIO' h sdoc)@ writes @sdoc@ to the handle @h@.+--+-- >>> let render = renderIO System.IO.stdout . layoutPretty defaultLayoutOptions+-- >>> let doc = annotate (color Red) ("red" <+> align (vsep [annotate (color Blue <> underlined) ("blue+u" <+> annotate bold "bold" <+> "blue+u"), "red"]))+--+-- We render the 'unAnnotate'd version here, since the ANSI codes don’t display+-- well in Haddock,+--+-- >>> render (unAnnotate doc)+-- red blue+u bold blue+u+-- red+--+-- This function behaves just like+--+-- @+-- 'renderIO' h sdoc = 'TL.hPutStr' h ('renderLazy' sdoc)+-- @+--+-- but will not generate any intermediate text, rendering directly to the+-- handle.+renderIO :: Handle -> SimpleDocStream AnsiStyle -> IO ()+renderIO h sdoc = do+ styleStackRef <- newIORef [mempty]++ let push x = modifyIORef' styleStackRef (x :)+ unsafePeek = readIORef styleStackRef >>= \tok -> case tok of+ [] -> panicPeekedEmpty+ x:_ -> pure x+ unsafePop = readIORef styleStackRef >>= \tok -> case tok of+ [] -> panicPoppedEmpty+ x:xs -> writeIORef styleStackRef xs >> pure x++ let go = \sds -> case sds of+ SFail -> panicUncaughtFail+ SEmpty -> pure ()+ SChar c rest -> do+ hPutChar h c+ go rest+ SText _ t rest -> do+ T.hPutStr h t+ go rest+ SLine i rest -> do+ hPutChar h '\n'+ T.hPutStr h (T.replicate i (T.singleton ' '))+ go rest+ SAnnPush style rest -> do+ currentStyle <- unsafePeek+ let newStyle = style <> currentStyle+ push newStyle+ T.hPutStr h (styleToRawText newStyle)+ go rest+ SAnnPop rest -> do+ _currentStyle <- unsafePop+ newStyle <- unsafePeek+ T.hPutStr h (styleToRawText newStyle)+ go rest+ go sdoc+ readIORef styleStackRef >>= \stack -> case stack of+ [] -> panicStyleStackFullyConsumed+ [_] -> pure ()+ xs -> panicStyleStackNotFullyConsumed (length xs)++panicStyleStackFullyConsumed :: void+panicStyleStackFullyConsumed+ = error ("There is no empty style left at the end of rendering" +++ " (but there should be). Please report this as a bug.")++panicStyleStackNotFullyConsumed :: Int -> void+panicStyleStackNotFullyConsumed len+ = error ("There are " <> show len <> " styles left at the" +++ "end of rendering (there should be only 1). Please report" +++ " this as a bug.")++-- $+-- >>> let render = renderIO System.IO.stdout . layoutPretty defaultLayoutOptions+-- >>> let doc = annotate (color Red) ("red" <+> align (vsep [annotate (color Blue <> underlined) ("blue+u" <+> annotate bold "bold" <+> "blue+u"), "red"]))+-- >>> render (unAnnotate doc)+-- red blue+u bold blue+u+-- red+--+-- This test won’t work since I don’t know how to type \ESC for doctest :-/+-- -- >>> render doc+-- -- \ESC[0;91mred \ESC[0;94;4mblue+u \ESC[0;94;1;4mbold\ESC[0;94;4m blue+u\ESC[0;91m+-- -- red\ESC[0m++-- | Render the annotated document in a certain style. Styles not set in the+-- annotation will use the style of the surrounding document, or the terminal’s+-- default if none has been set yet.+--+-- @+-- style = 'color' 'Green' '<>' 'bold'+-- styledDoc = 'annotate' style "hello world"+-- @+data AnsiStyle = SetAnsiStyle+ { ansiForeground :: Maybe (Intensity, Color) -- ^ Set the foreground color, or keep the old one.+ , ansiBackground :: Maybe (Intensity, Color) -- ^ Set the background color, or keep the old one.+ , ansiBold :: Maybe Bold -- ^ Switch on boldness, or don’t do anything.+ , ansiItalics :: Maybe Italicized -- ^ Switch on italics, or don’t do anything.+ , ansiUnderlining :: Maybe Underlined -- ^ Switch on underlining, or don’t do anything.+ } deriving (Eq, Ord, Show)++-- | Keep the first decision for each of foreground color, background color,+-- boldness, italication, and underlining. If a certain style is not set, the+-- terminal’s default will be used.+--+-- Example:+--+-- @+-- 'color' 'Red' '<>' 'color' 'Green'+-- @+--+-- is red because the first color wins, and not bold because (or if) that’s the+-- terminal’s default.+instance Semigroup AnsiStyle where+ cs1 <> cs2 = SetAnsiStyle+ { ansiForeground = ansiForeground cs1 <|> ansiForeground cs2+ , ansiBackground = ansiBackground cs1 <|> ansiBackground cs2+ , ansiBold = ansiBold cs1 <|> ansiBold cs2+ , ansiItalics = ansiItalics cs1 <|> ansiItalics cs2+ , ansiUnderlining = ansiUnderlining cs1 <|> ansiUnderlining cs2 }++-- | 'mempty' does nothing, which is equivalent to inheriting the style of the+-- surrounding doc, or the terminal’s default if no style has been set yet.+instance Monoid AnsiStyle where+ mempty = SetAnsiStyle Nothing Nothing Nothing Nothing Nothing+ mappend = (<>)++styleToRawText :: AnsiStyle -> Text+styleToRawText = T.pack . ANSI.setSGRCode . stylesToSgrs+ where+ stylesToSgrs :: AnsiStyle -> [ANSI.SGR]+ stylesToSgrs (SetAnsiStyle fg bg b i u) = catMaybes+ [ Just ANSI.Reset+ , fmap (\(intensity, c) -> ANSI.SetColor ANSI.Foreground (convertIntensity intensity) (convertColor c)) fg+ , fmap (\(intensity, c) -> ANSI.SetColor ANSI.Background (convertIntensity intensity) (convertColor c)) bg+ , fmap (\_ -> ANSI.SetConsoleIntensity ANSI.BoldIntensity) b+ , fmap (\_ -> ANSI.SetItalicized True) i+ , fmap (\_ -> ANSI.SetUnderlining ANSI.SingleUnderline) u+ ]++ convertIntensity :: Intensity -> ANSI.ColorIntensity+ convertIntensity = \i -> case i of+ Vivid -> ANSI.Vivid+ Dull -> ANSI.Dull++ convertColor :: Color -> ANSI.Color+ convertColor = \c -> case c of+ Black -> ANSI.Black+ Red -> ANSI.Red+ Green -> ANSI.Green+ Yellow -> ANSI.Yellow+ Blue -> ANSI.Blue+ Magenta -> ANSI.Magenta+ Cyan -> ANSI.Cyan+ White -> ANSI.White++++-- | @('renderStrict' sdoc)@ takes the output @sdoc@ from a rendering and+-- transforms it to strict text.+renderStrict :: SimpleDocStream AnsiStyle -> Text+renderStrict = TL.toStrict . renderLazy++-- | @('putDoc' doc)@ prettyprints document @doc@ to standard output using+-- 'defaultLayoutOptions'.+--+-- >>> putDoc ("hello" <+> "world")+-- hello world+--+-- @+-- 'putDoc' = 'hPutDoc' 'stdout'+-- @+putDoc :: Doc AnsiStyle -> IO ()+putDoc = hPutDoc stdout++-- | Like 'putDoc', but instead of using 'stdout', print to a user-provided+-- handle, e.g. a file or a socket using 'defaultLayoutOptions'.+--+-- > main = withFile "someFile.txt" (\h -> hPutDoc h (vcat ["vertical", "text"]))+--+-- @+-- 'hPutDoc' h doc = 'renderIO' h ('layoutPretty' 'defaultLayoutOptions' doc)+-- @+hPutDoc :: Handle -> Doc AnsiStyle -> IO ()+hPutDoc h doc = renderIO h (layoutPretty defaultLayoutOptions doc)