{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE TypeFamilies   #-}

-- | Default rendering to string types.

module Text.PrettyBy.Default
    ( layoutDef
    , Render (..)
    , display
    , displayBy
    ) where

import Text.Pretty
import Text.PrettyBy.Internal

import Data.Text qualified as Strict
import Data.Text.Lazy qualified as Lazy
import Prettyprinter.Render.String (renderString)
import Prettyprinter.Render.Text (renderLazy, renderStrict)

-- | A default layout for default rendering.
layoutDef :: Doc ann -> SimpleDocStream ann
layoutDef :: forall ann. Doc ann -> SimpleDocStream ann
layoutDef = forall ann. LayoutOptions -> Doc ann -> SimpleDocStream ann
layoutSmart LayoutOptions
defaultLayoutOptions

-- | A class for rendering 'Doc's as string types.
class Render str where
    -- | Render a 'Doc' as a string type.
    render :: Doc ann -> str

instance a ~ Char => Render [a] where
    render :: forall ann. Doc ann -> [a]
render = forall ann. SimpleDocStream ann -> String
renderString forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ann. Doc ann -> SimpleDocStream ann
layoutDef

instance Render Strict.Text where
    render :: forall ann. Doc ann -> Text
render = forall ann. SimpleDocStream ann -> Text
renderStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ann. Doc ann -> SimpleDocStream ann
layoutDef

instance Render Lazy.Text where
    render :: forall ann. Doc ann -> Text
render = forall ann. SimpleDocStream ann -> Text
renderLazy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ann. Doc ann -> SimpleDocStream ann
layoutDef

-- | Pretty-print and render a value as a string type.
display :: forall str a. (Pretty a, Render str) => a -> str
display :: forall str a. (Pretty a, Render str) => a -> str
display = forall str ann. Render str => Doc ann -> str
render forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
pretty

-- | Pretty-print and render a value as a string type in a configurable way.
displayBy :: forall str a config. (PrettyBy config a, Render str) => config -> a -> str
displayBy :: forall str a config.
(PrettyBy config a, Render str) =>
config -> a -> str
displayBy config
config = forall str ann. Render str => Doc ann -> str
render forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall config a ann. PrettyBy config a => config -> a -> Doc ann
prettyBy config
config