{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies, Safe #-}
module Text.Chatty.Printer where
import Control.Applicative
import Control.Arrow
import Control.Monad
import Control.Monad.State
import Control.Monad.Identity
import Control.Monad.Writer
import System.IO
class Monad m => ChPrinter m where
mprint :: String -> m ()
mnoecho :: String -> m ()
mnoecho = String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint
mflush :: m ()
mflush = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
mnomask :: String -> m ()
mnomask = String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint
instance ChPrinter IO where
mprint :: String -> IO ()
mprint = String -> IO ()
putStr
mnoecho :: String -> IO ()
mnoecho String
_ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
mflush :: IO ()
mflush = Handle -> IO ()
hFlush Handle
stdout
newtype DeafT m a = Deaf { DeafT m a -> m a
runDeafT :: m a }
instance Monad m => Monad (DeafT m) where
return :: a -> DeafT m a
return = m a -> DeafT m a
forall (m :: * -> *) a. m a -> DeafT m a
Deaf (m a -> DeafT m a) -> (a -> m a) -> a -> DeafT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
(Deaf m a
d) >>= :: DeafT m a -> (a -> DeafT m b) -> DeafT m b
>>= a -> DeafT m b
f = m b -> DeafT m b
forall (m :: * -> *) a. m a -> DeafT m a
Deaf (m b -> DeafT m b) -> m b -> DeafT m b
forall a b. (a -> b) -> a -> b
$ do a
d' <- m a
d; DeafT m b -> m b
forall (m :: * -> *) a. DeafT m a -> m a
runDeafT (a -> DeafT m b
f a
d')
instance MonadTrans DeafT where
lift :: m a -> DeafT m a
lift = m a -> DeafT m a
forall (m :: * -> *) a. m a -> DeafT m a
Deaf
instance (Functor m, Monad m) => Applicative (DeafT m) where
pure :: a -> DeafT m a
pure = a -> DeafT m a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: DeafT m (a -> b) -> DeafT m a -> DeafT m b
(<*>) = DeafT m (a -> b) -> DeafT m a -> DeafT m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Functor m => Functor (DeafT m) where
fmap :: (a -> b) -> DeafT m a -> DeafT m b
fmap a -> b
f (Deaf m a
a) = m b -> DeafT m b
forall (m :: * -> *) a. m a -> DeafT m a
Deaf (m b -> DeafT m b) -> m b -> DeafT m b
forall a b. (a -> b) -> a -> b
$ (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f m a
a
instance MonadIO m => MonadIO (DeafT m) where
liftIO :: IO a -> DeafT m a
liftIO = m a -> DeafT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> DeafT m a) -> (IO a -> m a) -> IO a -> DeafT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
instance Monad m => ChPrinter (DeafT m) where
mprint :: String -> DeafT m ()
mprint String
_ = () -> DeafT m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
newtype OutRedirT m a = OutRedir { OutRedirT m a -> Handle -> m a
runOutRedirT :: Handle -> m a }
type OutRedir = OutRedirT IO
instance Monad m => Monad (OutRedirT m) where
return :: a -> OutRedirT m a
return a
a = (Handle -> m a) -> OutRedirT m a
forall (m :: * -> *) a. (Handle -> m a) -> OutRedirT m a
OutRedir ((Handle -> m a) -> OutRedirT m a)
-> (Handle -> m a) -> OutRedirT m a
forall a b. (a -> b) -> a -> b
$ \Handle
h -> a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
(OutRedir Handle -> m a
r) >>= :: OutRedirT m a -> (a -> OutRedirT m b) -> OutRedirT m b
>>= a -> OutRedirT m b
f = (Handle -> m b) -> OutRedirT m b
forall (m :: * -> *) a. (Handle -> m a) -> OutRedirT m a
OutRedir ((Handle -> m b) -> OutRedirT m b)
-> (Handle -> m b) -> OutRedirT m b
forall a b. (a -> b) -> a -> b
$ \Handle
h -> do a
a <- Handle -> m a
r Handle
h; OutRedirT m b -> Handle -> m b
forall (m :: * -> *) a. OutRedirT m a -> Handle -> m a
runOutRedirT (a -> OutRedirT m b
f a
a) Handle
h
instance MonadTrans OutRedirT where
lift :: m a -> OutRedirT m a
lift m a
m = (Handle -> m a) -> OutRedirT m a
forall (m :: * -> *) a. (Handle -> m a) -> OutRedirT m a
OutRedir ((Handle -> m a) -> OutRedirT m a)
-> (Handle -> m a) -> OutRedirT m a
forall a b. (a -> b) -> a -> b
$ \Handle
h -> m a
m
instance MonadIO m => MonadIO (OutRedirT m) where
liftIO :: IO a -> OutRedirT m a
liftIO = m a -> OutRedirT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> OutRedirT m a) -> (IO a -> m a) -> IO a -> OutRedirT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
instance MonadIO m => ChPrinter (OutRedirT m) where
mprint :: String -> OutRedirT m ()
mprint String
s = (Handle -> m ()) -> OutRedirT m ()
forall (m :: * -> *) a. (Handle -> m a) -> OutRedirT m a
OutRedir ((Handle -> m ()) -> OutRedirT m ())
-> (Handle -> m ()) -> OutRedirT m ()
forall a b. (a -> b) -> a -> b
$ \Handle
h -> do IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle -> String -> IO ()
hPutStr Handle
h String
s; () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
mflush :: OutRedirT m ()
mflush = (Handle -> m ()) -> OutRedirT m ()
forall (m :: * -> *) a. (Handle -> m a) -> OutRedirT m a
OutRedir ((Handle -> m ()) -> OutRedirT m ())
-> (Handle -> m ()) -> OutRedirT m ()
forall a b. (a -> b) -> a -> b
$ \Handle
h -> do IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle -> IO ()
hFlush Handle
h; () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
instance Monad m => Functor (OutRedirT m) where
fmap :: (a -> b) -> OutRedirT m a -> OutRedirT m b
fmap a -> b
f OutRedirT m a
a = (Handle -> m b) -> OutRedirT m b
forall (m :: * -> *) a. (Handle -> m a) -> OutRedirT m a
OutRedir ((Handle -> m b) -> OutRedirT m b)
-> (Handle -> m b) -> OutRedirT m b
forall a b. (a -> b) -> a -> b
$ \Handle
h -> do a
a' <- OutRedirT m a -> Handle -> m a
forall (m :: * -> *) a. OutRedirT m a -> Handle -> m a
runOutRedirT OutRedirT m a
a Handle
h; b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> b
f a
a')
instance Monad m => Applicative (OutRedirT m) where
pure :: a -> OutRedirT m a
pure = a -> OutRedirT m a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: OutRedirT m (a -> b) -> OutRedirT m a -> OutRedirT m b
(<*>) = OutRedirT m (a -> b) -> OutRedirT m a -> OutRedirT m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
runOutRedir :: OutRedir a -> Handle -> IO a
runOutRedir :: OutRedir a -> Handle -> IO a
runOutRedir = OutRedir a -> Handle -> IO a
forall (m :: * -> *) a. OutRedirT m a -> Handle -> m a
runOutRedirT
runOutRedirFT :: (Functor m,MonadIO m) => OutRedirT m a -> FilePath -> IOMode -> m a
runOutRedirFT :: OutRedirT m a -> String -> IOMode -> m a
runOutRedirFT OutRedirT m a
m String
fp IOMode
md
| IOMode
md IOMode -> [IOMode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [IOMode
AppendMode,IOMode
WriteMode] = do
Handle
h <- IO Handle -> m Handle
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ String -> IOMode -> IO Handle
openFile String
fp IOMode
md
a
a <- OutRedirT m a -> Handle -> m a
forall (m :: * -> *) a. OutRedirT m a -> Handle -> m a
runOutRedirT OutRedirT m a
m Handle
h
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle -> IO ()
hClose Handle
h
a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
| Bool
otherwise = String -> m a
forall a. HasCallStack => String -> a
error String
"runOutRedirFT does only accept AppendMode or WriteMode."
runOutRedirF :: OutRedir a -> FilePath -> IOMode -> IO a
runOutRedirF :: OutRedir a -> String -> IOMode -> IO a
runOutRedirF = OutRedir a -> String -> IOMode -> IO a
forall (m :: * -> *) a.
(Functor m, MonadIO m) =>
OutRedirT m a -> String -> IOMode -> m a
runOutRedirFT
newtype RecorderT m a = Recorder { RecorderT m a -> m (a, [String])
runRecorderT' :: m (a,[String]) }
type Recorder = RecorderT Identity
instance Monad m => Monad (RecorderT m) where
return :: a -> RecorderT m a
return a
a = m (a, [String]) -> RecorderT m a
forall (m :: * -> *) a. m (a, [String]) -> RecorderT m a
Recorder (m (a, [String]) -> RecorderT m a)
-> m (a, [String]) -> RecorderT m a
forall a b. (a -> b) -> a -> b
$ (a, [String]) -> m (a, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a,[])
(Recorder m (a, [String])
r) >>= :: RecorderT m a -> (a -> RecorderT m b) -> RecorderT m b
>>= a -> RecorderT m b
f = m (b, [String]) -> RecorderT m b
forall (m :: * -> *) a. m (a, [String]) -> RecorderT m a
Recorder (m (b, [String]) -> RecorderT m b)
-> m (b, [String]) -> RecorderT m b
forall a b. (a -> b) -> a -> b
$ do
(a
a,[String]
s) <- m (a, [String])
r
(b
a',[String]
s') <- RecorderT m b -> m (b, [String])
forall (m :: * -> *) a. RecorderT m a -> m (a, [String])
runRecorderT' (a -> RecorderT m b
f a
a)
(b, [String]) -> m (b, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (b
a', [String]
s'[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String]
s)
instance MonadTrans RecorderT where
lift :: m a -> RecorderT m a
lift m a
m = m (a, [String]) -> RecorderT m a
forall (m :: * -> *) a. m (a, [String]) -> RecorderT m a
Recorder (m (a, [String]) -> RecorderT m a)
-> m (a, [String]) -> RecorderT m a
forall a b. (a -> b) -> a -> b
$ do a
a <- m a
m; (a, [String]) -> m (a, [String])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a,[])
instance Monad m => ChPrinter (RecorderT m) where
mprint :: String -> RecorderT m ()
mprint String
s = m ((), [String]) -> RecorderT m ()
forall (m :: * -> *) a. m (a, [String]) -> RecorderT m a
Recorder (m ((), [String]) -> RecorderT m ())
-> m ((), [String]) -> RecorderT m ()
forall a b. (a -> b) -> a -> b
$ ((), [String]) -> m ((), [String])
forall (m :: * -> *) a. Monad m => a -> m a
return ((),[String
s])
instance Monad m => Functor (RecorderT m) where
fmap :: (a -> b) -> RecorderT m a -> RecorderT m b
fmap = (a -> b) -> RecorderT m a -> RecorderT m b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM
instance Monad m => Applicative (RecorderT m) where
<*> :: RecorderT m (a -> b) -> RecorderT m a -> RecorderT m b
(<*>) = RecorderT m (a -> b) -> RecorderT m a -> RecorderT m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
pure :: a -> RecorderT m a
pure = a -> RecorderT m a
forall (m :: * -> *) a. Monad m => a -> m a
return
instance MonadIO m => MonadIO (RecorderT m) where
liftIO :: IO a -> RecorderT m a
liftIO = m a -> RecorderT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> RecorderT m a) -> (IO a -> m a) -> IO a -> RecorderT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
newtype Replayable = Replayable [String]
instance Show Replayable where
show :: Replayable -> String
show Replayable
r = Int -> String
forall a. Show a => a -> String
show ((\(Replayable [String]
x) -> [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
x) Replayable
r) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show (Replayable -> String
replay Replayable
r)
replay :: Replayable -> String
replay :: Replayable -> String
replay (Replayable [String]
r) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [a] -> [a]
reverse [String]
r
runRecorder :: Recorder a -> (a,Replayable)
runRecorder :: Recorder a -> (a, Replayable)
runRecorder = ([String] -> Replayable) -> (a, [String]) -> (a, Replayable)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second [String] -> Replayable
Replayable ((a, [String]) -> (a, Replayable))
-> (Recorder a -> (a, [String])) -> Recorder a -> (a, Replayable)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity (a, [String]) -> (a, [String])
forall a. Identity a -> a
runIdentity (Identity (a, [String]) -> (a, [String]))
-> (Recorder a -> Identity (a, [String]))
-> Recorder a
-> (a, [String])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Recorder a -> Identity (a, [String])
forall (m :: * -> *) a. RecorderT m a -> m (a, [String])
runRecorderT'
runRecorderT :: (Functor m,Monad m) => RecorderT m a -> m (a,Replayable)
runRecorderT :: RecorderT m a -> m (a, Replayable)
runRecorderT = ((a, [String]) -> (a, Replayable))
-> m (a, [String]) -> m (a, Replayable)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([String] -> Replayable) -> (a, [String]) -> (a, Replayable)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second [String] -> Replayable
Replayable) (m (a, [String]) -> m (a, Replayable))
-> (RecorderT m a -> m (a, [String]))
-> RecorderT m a
-> m (a, Replayable)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RecorderT m a -> m (a, [String])
forall (m :: * -> *) a. RecorderT m a -> m (a, [String])
runRecorderT'
mprintLn :: ChPrinter m => String -> m ()
mprintLn :: String -> m ()
mprintLn = String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint (String -> m ()) -> ShowS -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> ShowS
forall a. [a] -> [a] -> [a]
++String
"\n")
mnomaskLn :: ChPrinter m => String -> m ()
mnomaskLn :: String -> m ()
mnomaskLn = String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mnomask (String -> m ()) -> ShowS -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> ShowS
forall a. [a] -> [a] -> [a]
++String
"\n")
data DiscardO = DiscardO
data RecordO = RecordO
class RedirectionTarget t mt a r | t -> mt, t a -> r where
(.>.) :: (Functor m,MonadIO m,ChPrinter (mt m)) => mt m a -> t -> m r
(.>>.) :: (Functor m,MonadIO m,ChPrinter (mt m)) => mt m a -> t -> m r
(.>>.) = mt m a -> t -> m r
forall t (mt :: (* -> *) -> * -> *) a r (m :: * -> *).
(RedirectionTarget t mt a r, Functor m, MonadIO m,
ChPrinter (mt m)) =>
mt m a -> t -> m r
(.>.)
instance RedirectionTarget DiscardO DeafT a a where
DeafT m a
m .>. :: DeafT m a -> DiscardO -> m a
.>. DiscardO
_ = DeafT m a -> m a
forall (m :: * -> *) a. DeafT m a -> m a
runDeafT DeafT m a
m
instance RedirectionTarget RecordO RecorderT a (a,Replayable) where
RecorderT m a
m .>. :: RecorderT m a -> RecordO -> m (a, Replayable)
.>. RecordO
_ = RecorderT m a -> m (a, Replayable)
forall (m :: * -> *) a.
(Functor m, Monad m) =>
RecorderT m a -> m (a, Replayable)
runRecorderT RecorderT m a
m
instance RedirectionTarget FilePath OutRedirT a a where
OutRedirT m a
m .>. :: OutRedirT m a -> String -> m a
.>. String
fp = OutRedirT m a -> String -> IOMode -> m a
forall (m :: * -> *) a.
(Functor m, MonadIO m) =>
OutRedirT m a -> String -> IOMode -> m a
runOutRedirFT OutRedirT m a
m String
fp IOMode
WriteMode
OutRedirT m a
m .>>. :: OutRedirT m a -> String -> m a
.>>. String
fp = OutRedirT m a -> String -> IOMode -> m a
forall (m :: * -> *) a.
(Functor m, MonadIO m) =>
OutRedirT m a -> String -> IOMode -> m a
runOutRedirFT OutRedirT m a
m String
fp IOMode
AppendMode
instance RedirectionTarget Handle OutRedirT a a where
OutRedirT m a
m .>. :: OutRedirT m a -> Handle -> m a
.>. Handle
fp = OutRedirT m a -> Handle -> m a
forall (m :: * -> *) a. OutRedirT m a -> Handle -> m a
runOutRedirT OutRedirT m a
m Handle
fp