module Text.Render (
Render(..), Indenter,
indented, wrapIndented, inNewLine, renderIndented,
renderIndentedStartingAt,
renderTicks
) where
import ClassyPrelude
import qualified Prelude as P
import Control.Monad.Trans (MonadIO(..))
import Control.Monad.Reader (ReaderT(..), MonadReader(..), (<=<), (>=>), ask,
asks, runReaderT)
import Control.Monad.Writer (WriterT(..), MonadWriter(..), runWriterT)
import Control.Monad.State.Strict (MonadState, StateT, State, get, gets,
modify, put, liftM, liftIO, runState,
runStateT, execState, execStateT,
evalState, evalStateT)
import Data.Text (Text)
import qualified Data.Text as T
import Text.Parsec (ParseError)
type Name = Text
class Show a => Render a where
render :: a -> Text
render = T.pack . P.show
renderParens :: a -> Text
renderParens = render
renderIO :: MonadIO m => a -> m Text
renderIO = return . render
renderI :: a -> Indenter
renderI = tell . render
instance Render Int
instance Render Bool
instance Render Integer
instance Render Double
instance Render Text
instance Render ParseError
instance (Render a, Render b) => Render (a, b) where
render (a, b) = "(" <> render a <> ", " <> render b <> ")"
instance Render a => Render [a] where
render list = "[" <> T.intercalate ", " (map render list) <> "]"
renderTicks :: Render a => a -> Text
renderTicks x = "`" <> render x <> "`"
type Indenter = ReaderT Int (WriterT Text (State Int)) ()
indented :: Indenter -> Indenter
indented action = do
c <- get
put (c+1)
action
put c
inNewLine :: Indenter -> Indenter
inNewLine action = do
ilevel <- ask
current <- get
tell $ "\n" <> T.replicate (ilevel * current) " "
action
wrapIndented :: Render a => Text -> Text -> [a] -> Indenter
wrapIndented start finish things = do
tell start
indented $ mapM_ (inNewLine . renderI) things
inNewLine $ tell finish
renderIndented :: Render a => Int -> a -> Text
renderIndented = renderIndentedStartingAt 0
renderIndentedStartingAt :: Render a => Int -> Int -> a -> Text
renderIndentedStartingAt start level e =
snd $ evalState (runWriterT (runReaderT (renderI e) level)) start