{-# OPTIONS_HADDOCK hide #-}
module Text.EscapeArtist.Internal (Escapable(..), ToEscapable(..), putEscLn, putEsc, escToString, (^$), (/<>/)) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Lazy.Char8 as BSLC
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Typeable (Typeable, cast)
import Data.Word (Word, Word8, Word16, Word32, Word64)
import Text.EscapeArtist.Internal.Constants
#if ! MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
infixr 7 ^$
(^$) :: (a -> b) -> a -> b
(^$) = ($)
data Escapable = forall a. (ToEscapable a) => FgBlack a
| forall a. (ToEscapable a) => FgRed a
| forall a. (ToEscapable a) => FgGreen a
| forall a. (ToEscapable a) => FgYellow a
| forall a. (ToEscapable a) => FgBlue a
| forall a. (ToEscapable a) => FgMagenta a
| forall a. (ToEscapable a) => FgCyan a
| forall a. (ToEscapable a) => FgWhite a
| forall a. (ToEscapable a) => BgBlack a
| forall a. (ToEscapable a) => BgRed a
| forall a. (ToEscapable a) => BgGreen a
| forall a. (ToEscapable a) => BgYellow a
| forall a. (ToEscapable a) => BgBlue a
| forall a. (ToEscapable a) => BgMagenta a
| forall a. (ToEscapable a) => BgCyan a
| forall a. (ToEscapable a) => BgWhite a
| forall a. (ToEscapable a) => FgDefault a
| forall a. (ToEscapable a) => BgDefault a
| forall a. (ToEscapable a) => Inherit a
| forall a. (ToEscapable a) => Default a
| forall a. (ToEscapable a) => Blink a
| forall a. (ToEscapable a) => BlinkOff a
| forall a. (ToEscapable a) => Bright a
| forall a. (ToEscapable a) => BrightOff a
| forall a. (ToEscapable a) => Underline a
| forall a. (ToEscapable a) => UnderlineOff a
| forall a. (ToEscapable a) => Inverse a
| forall a. (ToEscapable a) => InverseOff a
| Sum [Escapable]
| Atom String
instance Show Escapable where
show (FgBlack a) = "FgBlack (" ++ show a ++ ")"
show (FgRed a) = "FgRed (" ++ show a ++ ")"
show (FgGreen a) = "FgGreen (" ++ show a ++ ")"
show (FgYellow a) = "FgYellow (" ++ show a ++ ")"
show (FgBlue a) = "FgBlue (" ++ show a ++ ")"
show (FgMagenta a) = "FgMagenta (" ++ show a ++ ")"
show (FgCyan a) = "FgCyan (" ++ show a ++ ")"
show (FgWhite a) = "FgWhite (" ++ show a ++ ")"
show (BgBlack a) = "BgBlack (" ++ show a ++ ")"
show (BgRed a) = "BgRed (" ++ show a ++ ")"
show (BgGreen a) = "BgGreen (" ++ show a ++ ")"
show (BgYellow a) = "BgYellow (" ++ show a ++ ")"
show (BgBlue a) = "BgBlue (" ++ show a ++ ")"
show (BgMagenta a) = "BgMagenta (" ++ show a ++ ")"
show (BgCyan a) = "BgCyan (" ++ show a ++ ")"
show (BgWhite a) = "BgWhite (" ++ show a ++ ")"
show (FgDefault a) = "FgDefault (" ++ show a ++ ")"
show (BgDefault a) = "BgDefault (" ++ show a ++ ")"
show (Inherit a) = "Inherit (" ++ show a ++ ")"
show (Default a) = "Default (" ++ show a ++ ")"
show (Blink a) = "Blink (" ++ show a ++ ")"
show (BlinkOff a) = "BlinkOff (" ++ show a ++ ")"
show (Bright a) = "Bright (" ++ show a ++ ")"
show (BrightOff a) = "BrightOff (" ++ show a ++ ")"
show (Underline a) = "Underline (" ++ show a ++ ")"
show (UnderlineOff a) = "UnderlineOff (" ++ show a ++ ")"
show (Inverse a) = "Inverse (" ++ show a ++ ")"
show (InverseOff a) = "InverseOff (" ++ show a ++ ")"
show (Sum a) = "Sum " ++ show a
show (Atom a) = "Atom " ++ show a
extEq :: forall a b. (Eq a, Eq b, Typeable a, Typeable b) => a -> b -> Bool
extEq x y = case cast x of
Nothing -> False
Just x' -> x' == y
instance Eq Escapable where
(FgBlack a) == (FgBlack b) = extEq a b
(FgRed a) == (FgRed b) = extEq a b
(FgGreen a) == (FgGreen b) = extEq a b
(FgYellow a) == (FgYellow b) = extEq a b
(FgBlue a) == (FgBlue b) = extEq a b
(FgMagenta a) == (FgMagenta b) = extEq a b
(FgCyan a) == (FgCyan b) = extEq a b
(FgWhite a) == (FgWhite b) = extEq a b
(BgBlack a) == (BgBlack b) = extEq a b
(BgRed a) == (BgRed b) = extEq a b
(BgGreen a) == (BgGreen b) = extEq a b
(BgYellow a) == (BgYellow b) = extEq a b
(BgBlue a) == (BgBlue b) = extEq a b
(BgMagenta a) == (BgMagenta b) = extEq a b
(BgCyan a) == (BgCyan b) = extEq a b
(BgWhite a) == (BgWhite b) = extEq a b
(FgDefault a) == (FgDefault b) = extEq a b
(BgDefault a) == (BgDefault b) = extEq a b
(Inherit a) == (Inherit b) = extEq a b
(Default a) == (Default b) = extEq a b
(Blink a) == (Blink b) = extEq a b
(BlinkOff a) == (BlinkOff b) = extEq a b
(Bright a) == (Bright b) = extEq a b
(BrightOff a) == (BrightOff b) = extEq a b
(Underline a) == (Underline b) = extEq a b
(UnderlineOff a) == (UnderlineOff b) = extEq a b
(Inverse a) == (Inverse b) = extEq a b
(InverseOff a) == (InverseOff b) = extEq a b
(Sum a) == (Sum b) = extEq a b
(Atom a) == (Atom b) = extEq a b
_ == _ = False
class (Show a, Typeable a, Eq a) => ToEscapable a where
toEscapable :: a -> Escapable
instance ToEscapable String where
toEscapable = Atom
instance ToEscapable Char where
toEscapable a = Atom [a]
instance ToEscapable BS.ByteString where
toEscapable a = Atom $ BSC.unpack a
instance ToEscapable BSL.ByteString where
toEscapable a = Atom $ BSLC.unpack a
instance ToEscapable T.Text where
toEscapable a = Atom $ T.unpack a
instance ToEscapable TL.Text where
toEscapable a = Atom $ TL.unpack a
instance ToEscapable Int where
toEscapable a = Atom $ show a
instance ToEscapable Integer where
toEscapable a = Atom $ show a
instance ToEscapable Word where
toEscapable a = Atom $ show a
instance ToEscapable Word8 where
toEscapable a = Atom $ show a
instance ToEscapable Word16 where
toEscapable a = Atom $ show a
instance ToEscapable Word32 where
toEscapable a = Atom $ show a
instance ToEscapable Word64 where
toEscapable a = Atom $ show a
instance ToEscapable Float where
toEscapable a = Atom $ show a
instance ToEscapable Double where
toEscapable a = Atom $ show a
instance ToEscapable Escapable where
toEscapable = id
escToString :: (ToEscapable a) => a -> String
escToString esc = escToStrEncl "" "" $ toEscapable esc
recur :: String -> String -> Escapable -> String
recur = escToStrEncl
dc :: String
dc = defaultFgColor
dbc :: String
dbc = defaultBgColor
def :: String
def = defaultAll
te :: (ToEscapable a) => a -> Escapable
te = toEscapable
escToStrEncl :: String -> String -> Escapable -> String
escToStrEncl pref suff (FgBlack a) = recur (pref ++ fgBlack ) (dc ++ suff) (te a)
escToStrEncl pref suff (FgRed a) = recur (pref ++ fgRed ) (dc ++ suff) (te a)
escToStrEncl pref suff (FgGreen a) = recur (pref ++ fgGreen ) (dc ++ suff) (te a)
escToStrEncl pref suff (FgYellow a) = recur (pref ++ fgYellow ) (dc ++ suff) (te a)
escToStrEncl pref suff (FgBlue a) = recur (pref ++ fgBlue ) (dc ++ suff) (te a)
escToStrEncl pref suff (FgMagenta a) = recur (pref ++ fgMagenta) (dc ++ suff) (te a)
escToStrEncl pref suff (FgCyan a) = recur (pref ++ fgCyan ) (dc ++ suff) (te a)
escToStrEncl pref suff (FgWhite a) = recur (pref ++ fgWhite ) (dc ++ suff) (te a)
escToStrEncl pref suff (BgBlack a) = recur (pref ++ bgBlack ) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgRed a) = recur (pref ++ bgRed ) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgGreen a) = recur (pref ++ bgGreen ) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgYellow a) = recur (pref ++ bgYellow ) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgBlue a) = recur (pref ++ bgBlue ) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgMagenta a) = recur (pref ++ bgMagenta) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgCyan a) = recur (pref ++ bgCyan ) (dbc ++ suff) (te a)
escToStrEncl pref suff (BgWhite a) = recur (pref ++ bgWhite ) (dbc ++ suff) (te a)
escToStrEncl pref suff (FgDefault a) = recur (pref ++ dc ) suff (te a)
escToStrEncl pref suff (BgDefault a) = recur (pref ++ dbc) suff (te a)
escToStrEncl pref suff (Inherit a) = recur pref suff (te a)
escToStrEncl pref suff (Default a) = recur (pref ++ def) suff (te a)
escToStrEncl pref suff (Blink a) = recur (pref ++ blinkOn ) (blinkOff ++ suff) (te a)
escToStrEncl pref suff (BlinkOff a) = recur (pref ++ blinkOff ) suff (te a)
escToStrEncl pref suff (Bright a) = recur (pref ++ brightOn ) (brightOff ++ suff) (te a)
escToStrEncl pref suff (BrightOff a) = recur (pref ++ brightOff ) suff (te a)
escToStrEncl pref suff (Underline a) = recur (pref ++ underlineOn ) (underlineOff ++ suff) (te a)
escToStrEncl pref suff (UnderlineOff a) = recur (pref ++ underlineOff) suff (te a)
escToStrEncl pref suff (Inverse a) = recur (pref ++ inverseOn ) (inverseOff ++ suff) (te a)
escToStrEncl pref suff (InverseOff a) = recur (pref ++ inverseOff ) suff (te a)
escToStrEncl pref suff (Sum a) = concatMap (recur pref suff) a
escToStrEncl pref suff (Atom a) = concat [pref, a, suff]
#if MIN_VERSION_base(4,11,0)
instance Semigroup Escapable where
(<>) (Sum []) b = b
(<>) a (Sum []) = a
(<>) (Sum as) (Sum bs) = Sum $ as ++ bs
(<>) (Sum as) b = Sum $ as ++ [b]
(<>) a (Sum bs) = Sum $ a : bs
(<>) a b = Sum [a, b]
#endif
instance Monoid Escapable where
mempty = Sum []
#if ! MIN_VERSION_base(4,11,0)
mappend (Sum []) b = b
mappend a (Sum []) = a
mappend (Sum as) (Sum bs) = Sum $ mconcat [as, bs ]
mappend (Sum as) b = Sum $ mconcat [as, [b]]
mappend a (Sum bs) = Sum $ mconcat [[a], bs ]
mappend a b = Sum [a, b]
#endif
defInherit :: forall a. (ToEscapable a, Typeable a) => a -> Escapable
defInherit a = case cast a of
Nothing -> Inherit a
Just a' -> a'
infixr 6 /<>/
(/<>/) :: forall a b. (ToEscapable a, ToEscapable b) => a -> b -> Escapable
(/<>/) a b = defInherit a <> defInherit b
putEscLn :: (ToEscapable a) => a -> IO ()
putEscLn = putStrLn . escToString
putEsc :: (ToEscapable a) => a -> IO ()
putEsc = putStr . escToString