{-# LANGUAGE OverloadedStrings #-}

module Data.Text.Prettyprint.Doc.Ext ( prettyText
                                     , prettyLazyText
                                     , smartDickinson
                                     , dickinsonText
                                     , dickinsonLazyText
                                     , intercalate
                                     , hardSep
                                     , prettyDumpBinds
                                     -- * Debug class
                                     , Debug (..)
                                     -- * Operators
                                     , (<#>)
                                     , (<:>)
                                     , (<^>)
                                     , (<#*>)
                                     ) where

import qualified Data.IntMap               as IM
import           Data.List                 (intersperse)
import           Data.Semigroup            ((<>))
import qualified Data.Text                 as T
import qualified Data.Text.Lazy            as TL
import           Prettyprinter             (Doc, LayoutOptions (LayoutOptions), PageWidth (AvailablePerLine), Pretty (pretty), SimpleDocStream, concatWith,
                                            flatAlt, hardline, indent, layoutSmart, softline, vsep, (<+>))
import           Prettyprinter.Render.Text (renderLazy, renderStrict)

infixr 6 <#>
infixr 6 <:>
infixr 6 <^>

class Debug a where
    debug :: a -> Doc b

(<#>) :: Doc a -> Doc a -> Doc a
<#> :: forall a. Doc a -> Doc a -> Doc a
(<#>) Doc a
x Doc a
y = Doc a
x forall a. Semigroup a => a -> a -> a
<> forall ann. Doc ann
hardline forall a. Semigroup a => a -> a -> a
<> Doc a
y

(<:>) :: Doc a -> Doc a -> Doc a
<:> :: forall a. Doc a -> Doc a -> Doc a
(<:>) Doc a
x Doc a
y = Doc a
x forall a. Semigroup a => a -> a -> a
<> forall ann. Doc ann
softline forall a. Semigroup a => a -> a -> a
<> Doc a
y

(<#*>) :: Doc a -> Doc a -> Doc a
<#*> :: forall a. Doc a -> Doc a -> Doc a
(<#*>) Doc a
x Doc a
y = Doc a
x forall a. Semigroup a => a -> a -> a
<> forall ann. Doc ann
hardline forall a. Semigroup a => a -> a -> a
<> forall ann. Int -> Doc ann -> Doc ann
indent Int
2 Doc a
y

(<^>) :: Doc a -> Doc a -> Doc a
<^> :: forall a. Doc a -> Doc a -> Doc a
(<^>) Doc a
x Doc a
y = forall a. Doc a -> Doc a -> Doc a
flatAlt (Doc a
x forall a. Semigroup a => a -> a -> a
<> forall ann. Doc ann
hardline forall a. Semigroup a => a -> a -> a
<> forall ann. Int -> Doc ann -> Doc ann
indent Int
2 Doc a
y) (Doc a
x forall a. Doc a -> Doc a -> Doc a
<+> Doc a
y)

prettyDumpBinds :: Pretty b => IM.IntMap b -> Doc a
prettyDumpBinds :: forall b a. Pretty b => IntMap b -> Doc a
prettyDumpBinds IntMap b
b = forall ann. [Doc ann] -> Doc ann
vsep (forall b a. Pretty b => (Int, b) -> Doc a
prettyBind forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. IntMap a -> [(Int, a)]
IM.toList IntMap b
b)

prettyBind :: Pretty b => (Int, b) -> Doc a
prettyBind :: forall b a. Pretty b => (Int, b) -> Doc a
prettyBind (Int
i, b
j) = forall a ann. Pretty a => a -> Doc ann
pretty Int
i forall a. Doc a -> Doc a -> Doc a
<+> Doc a
"→" forall a. Doc a -> Doc a -> Doc a
<+> forall a ann. Pretty a => a -> Doc ann
pretty b
j

hardSep :: [Doc ann] -> Doc ann
hardSep :: forall ann. [Doc ann] -> Doc ann
hardSep = forall (t :: * -> *) ann.
Foldable t =>
(Doc ann -> Doc ann -> Doc ann) -> t (Doc ann) -> Doc ann
concatWith forall a. Doc a -> Doc a -> Doc a
(<#>)

intercalate :: Doc a -> [Doc a] -> Doc a
intercalate :: forall a. Doc a -> [Doc a] -> Doc a
intercalate Doc a
x = forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
intersperse Doc a
x

dickinsonLayoutOptions :: LayoutOptions
dickinsonLayoutOptions :: LayoutOptions
dickinsonLayoutOptions = PageWidth -> LayoutOptions
LayoutOptions (Int -> Double -> PageWidth
AvailablePerLine Int
160 Double
0.8)

-- TODO: use layoutCompact for errors?

smartDickinson :: Doc a -> SimpleDocStream a
smartDickinson :: forall a. Doc a -> SimpleDocStream a
smartDickinson = forall ann. LayoutOptions -> Doc ann -> SimpleDocStream ann
layoutSmart LayoutOptions
dickinsonLayoutOptions

dickinsonText :: Doc a -> T.Text
dickinsonText :: forall a. Doc a -> Text
dickinsonText = forall ann. SimpleDocStream ann -> Text
renderStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Doc a -> SimpleDocStream a
smartDickinson

dickinsonLazyText :: Doc a -> TL.Text
dickinsonLazyText :: forall a. Doc a -> Text
dickinsonLazyText = forall ann. SimpleDocStream ann -> Text
renderLazy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Doc a -> SimpleDocStream a
smartDickinson

prettyText :: Pretty a => a -> T.Text
prettyText :: forall a. Pretty a => a -> Text
prettyText = forall a. Doc a -> Text
dickinsonText forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
pretty

prettyLazyText :: Pretty a => a -> TL.Text
prettyLazyText :: forall a. Pretty a => a -> Text
prettyLazyText = forall a. Doc a -> Text
dickinsonLazyText forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
pretty