{-# LANGUAGE Safe #-}
module Text.Chatty.Extended.ANSI where
import qualified System.Console.ANSI as A
import Control.Applicative
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.IO.Class
import Text.Chatty.Printer
import Text.Chatty.Extended.Printer
import Text.Chatty.Expansion
newtype AnsiPrinterT m a = AnsiPrinter { AnsiPrinterT m a -> [Colour] -> m (a, [Colour])
runAnsiPrinterT :: [Colour] -> m (a,[Colour]) }
instance Monad m => Monad (AnsiPrinterT m) where
return :: a -> AnsiPrinterT m a
return a
a = ([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a)
-> ([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
forall a b. (a -> b) -> a -> b
$ \[Colour]
s -> (a, [Colour]) -> m (a, [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a,[Colour]
s)
(AnsiPrinter [Colour] -> m (a, [Colour])
p) >>= :: AnsiPrinterT m a -> (a -> AnsiPrinterT m b) -> AnsiPrinterT m b
>>= a -> AnsiPrinterT m b
f = ([Colour] -> m (b, [Colour])) -> AnsiPrinterT m b
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m (b, [Colour])) -> AnsiPrinterT m b)
-> ([Colour] -> m (b, [Colour])) -> AnsiPrinterT m b
forall a b. (a -> b) -> a -> b
$ \[Colour]
s -> do (a
a,[Colour]
s') <- [Colour] -> m (a, [Colour])
p [Colour]
s; AnsiPrinterT m b -> [Colour] -> m (b, [Colour])
forall (m :: * -> *) a.
AnsiPrinterT m a -> [Colour] -> m (a, [Colour])
runAnsiPrinterT (a -> AnsiPrinterT m b
f a
a) [Colour]
s'
instance MonadTrans AnsiPrinterT where
lift :: m a -> AnsiPrinterT m a
lift m a
m = ([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a)
-> ([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
forall a b. (a -> b) -> a -> b
$ \[Colour]
c -> do a
a <- m a
m; (a, [Colour]) -> m (a, [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a,[Colour]
c)
instance Monad m => Functor (AnsiPrinterT m) where
fmap :: (a -> b) -> AnsiPrinterT m a -> AnsiPrinterT m b
fmap a -> b
f AnsiPrinterT m a
a = ([Colour] -> m (b, [Colour])) -> AnsiPrinterT m b
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m (b, [Colour])) -> AnsiPrinterT m b)
-> ([Colour] -> m (b, [Colour])) -> AnsiPrinterT m b
forall a b. (a -> b) -> a -> b
$ \[Colour]
s -> do (a
a',[Colour]
s') <- AnsiPrinterT m a -> [Colour] -> m (a, [Colour])
forall (m :: * -> *) a.
AnsiPrinterT m a -> [Colour] -> m (a, [Colour])
runAnsiPrinterT AnsiPrinterT m a
a [Colour]
s; (b, [Colour]) -> m (b, [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> b
f a
a',[Colour]
s')
instance Monad m => Applicative (AnsiPrinterT m) where
pure :: a -> AnsiPrinterT m a
pure = a -> AnsiPrinterT m a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: AnsiPrinterT m (a -> b) -> AnsiPrinterT m a -> AnsiPrinterT m b
(<*>) = AnsiPrinterT m (a -> b) -> AnsiPrinterT m a -> AnsiPrinterT m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance MonadIO m => MonadIO (AnsiPrinterT m) where
liftIO :: IO a -> AnsiPrinterT m a
liftIO = m a -> AnsiPrinterT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> AnsiPrinterT m a)
-> (IO a -> m a) -> IO a -> AnsiPrinterT 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 ChPrinter m => ChPrinter (AnsiPrinterT m) where
mprint :: String -> AnsiPrinterT m ()
mprint = m () -> AnsiPrinterT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> AnsiPrinterT m ())
-> (String -> m ()) -> String -> AnsiPrinterT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint
mnoecho :: String -> AnsiPrinterT m ()
mnoecho = m () -> AnsiPrinterT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> AnsiPrinterT m ())
-> (String -> m ()) -> String -> AnsiPrinterT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mnoecho
mflush :: AnsiPrinterT m ()
mflush = m () -> AnsiPrinterT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m ()
forall (m :: * -> *). ChPrinter m => m ()
mflush
mnomask :: String -> AnsiPrinterT m ()
mnomask = m () -> AnsiPrinterT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> AnsiPrinterT m ())
-> (String -> m ()) -> String -> AnsiPrinterT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mnomask
instance ChPrinter m => ChExtendedPrinter (AnsiPrinterT m) where
estart :: Colour -> AnsiPrinterT m ()
estart Colour
c = ([Colour] -> m ((), [Colour])) -> AnsiPrinterT m ()
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m ((), [Colour])) -> AnsiPrinterT m ())
-> ([Colour] -> m ((), [Colour])) -> AnsiPrinterT m ()
forall a b. (a -> b) -> a -> b
$ \[Colour]
c1 -> do
String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ [SGR] -> String
A.setSGRCode [ConsoleLayer -> ColorIntensity -> Color -> SGR
A.SetColor ConsoleLayer
A.Foreground (Colour -> ColorIntensity
mkColourInt Colour
c) (Colour -> Color
mkColourCode Colour
c)]
((), [Colour]) -> m ((), [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return ((),Colour
cColour -> [Colour] -> [Colour]
forall a. a -> [a] -> [a]
:[Colour]
c1)
efin :: AnsiPrinterT m ()
efin = ([Colour] -> m ((), [Colour])) -> AnsiPrinterT m ()
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m ((), [Colour])) -> AnsiPrinterT m ())
-> ([Colour] -> m ((), [Colour])) -> AnsiPrinterT m ()
forall a b. (a -> b) -> a -> b
$ \[Colour]
c1 ->
case [Colour]
c1 of
(Colour
_:Colour
c:[Colour]
cx) -> do
String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ [SGR] -> String
A.setSGRCode [ConsoleLayer -> ColorIntensity -> Color -> SGR
A.SetColor ConsoleLayer
A.Foreground (Colour -> ColorIntensity
mkColourInt Colour
c) (Colour -> Color
mkColourCode Colour
c)]
((), [Colour]) -> m ((), [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return ((),Colour
cColour -> [Colour] -> [Colour]
forall a. a -> [a] -> [a]
:[Colour]
cx)
[Colour]
_ -> do
String -> m ()
forall (m :: * -> *). ChPrinter m => String -> m ()
mprint (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ [SGR] -> String
A.setSGRCode [SGR
A.Reset]
((), [Colour]) -> m ((), [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return ((),[])
instance (Functor m,ChExpand m) => ChExpand (AnsiPrinterT m) where
expand :: String -> AnsiPrinterT m String
expand String
s = ([Colour] -> m (String, [Colour])) -> AnsiPrinterT m String
forall (m :: * -> *) a.
([Colour] -> m (a, [Colour])) -> AnsiPrinterT m a
AnsiPrinter (([Colour] -> m (String, [Colour])) -> AnsiPrinterT m String)
-> ([Colour] -> m (String, [Colour])) -> AnsiPrinterT m String
forall a b. (a -> b) -> a -> b
$ \[Colour]
cx -> do
String
s1 <- (String -> m String
forall (e :: * -> *). ChExpand e => String -> e String
expand (String -> m String) -> m String -> m String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) (m String -> m String) -> m String -> m String
forall a b. (a -> b) -> a -> b
$ (((), Replayable) -> String) -> m ((), Replayable) -> m String
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Replayable -> String
replay(Replayable -> String)
-> (((), Replayable) -> Replayable) -> ((), Replayable) -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((), Replayable) -> Replayable
forall a b. (a, b) -> b
snd) (m ((), Replayable) -> m String) -> m ((), Replayable) -> m String
forall a b. (a -> b) -> a -> b
$ RecorderT m () -> m ((), Replayable)
forall (m :: * -> *) a.
(Functor m, Monad m) =>
RecorderT m a -> m (a, Replayable)
runRecorderT (RecorderT m () -> m ((), Replayable))
-> RecorderT m () -> m ((), Replayable)
forall a b. (a -> b) -> a -> b
$ (((), [Colour]) -> ())
-> RecorderT m ((), [Colour]) -> RecorderT m ()
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((), [Colour]) -> ()
forall a b. (a, b) -> a
fst (RecorderT m ((), [Colour]) -> RecorderT m ())
-> RecorderT m ((), [Colour]) -> RecorderT m ()
forall a b. (a -> b) -> a -> b
$ (AnsiPrinterT (RecorderT m) ()
-> [Colour] -> RecorderT m ((), [Colour]))
-> [Colour]
-> AnsiPrinterT (RecorderT m) ()
-> RecorderT m ((), [Colour])
forall a b c. (a -> b -> c) -> b -> a -> c
flip AnsiPrinterT (RecorderT m) ()
-> [Colour] -> RecorderT m ((), [Colour])
forall (m :: * -> *) a.
AnsiPrinterT m a -> [Colour] -> m (a, [Colour])
runAnsiPrinterT [Colour]
cx (AnsiPrinterT (RecorderT m) () -> RecorderT m ((), [Colour]))
-> AnsiPrinterT (RecorderT m) () -> RecorderT m ((), [Colour])
forall a b. (a -> b) -> a -> b
$ String -> AnsiPrinterT (RecorderT m) ()
forall (m :: * -> *). ChExtendedPrinter m => String -> m ()
expandClr String
s
(String, [Colour]) -> m (String, [Colour])
forall (m :: * -> *) a. Monad m => a -> m a
return (String
s1, [Colour]
cx)
mkColourInt :: Colour -> ColorIntensity
mkColourInt (Dull Tone
_) = ColorIntensity
A.Dull
mkColourInt (Vivid Tone
_) = ColorIntensity
A.Vivid
mkColourCode :: Colour -> Color
mkColourCode (Dull Tone
c) = Colour -> Color
mkColourCode (Tone -> Colour
Vivid Tone
c)
mkColourCode (Vivid Tone
c) = case Tone
c of
Tone
Green -> Color
A.Green
Tone
Red -> Color
A.Red
Tone
Yellow -> Color
A.Yellow
Tone
Blue -> Color
A.Blue
Tone
Black -> Color
A.Black
Tone
White -> Color
A.White
Tone
Cyan -> Color
A.Cyan
Tone
Magenta -> Color
A.Magenta