module Pretty (
Pretty (..),
pretty,
PrettyM,
ShortText,
Doc,
sexpr,
fresh,
PP.text,
PP.integer,
) where
import Control.Monad.Trans.State.Strict
import Data.Text.Short (ShortText)
import Data.Char (isDigit)
import qualified Data.Text.Short as TS
import qualified Text.PrettyPrint as PP
import qualified Data.Set as Set
type S = Set.Set ShortText
type Doc = PP.Doc
type PrettyM = State S
pretty :: Pretty a => a -> String
pretty x = PP.render (evalState (ppr x) Set.empty)
markUsed :: ShortText -> State S ()
markUsed t = modify' (Set.insert t)
sexpr :: Doc -> [Doc] -> Doc
sexpr car cdr = PP.parens $ PP.hang car 2 $ PP.sep cdr
fresh :: String -> PrettyM String
fresh s = state (pick names)
where
pick [] u = (s, u) -- shouldn't happen, names is infinite
pick (x : xs) u
| x' `Set.member` u = pick xs u
| otherwise = (x, Set.insert x' u)
where
x' = TS.pack x
names = n : [ n ++ show m | m <- [d .. ] ]
(ds, rn) = span isDigit (reverse s)
n :: String
n = reverse rn
d :: Int
d = case ds of
[] -> 0
_ -> read (reverse ds)
class Pretty a where
ppr :: a -> PrettyM Doc
instance Pretty ShortText where
ppr t = do
markUsed t
return $ PP.text $ TS.unpack t