{-# LANGUAGE BangPatterns #-}
module Graphics.Vty.Inline
( module Graphics.Vty.Inline
, withVty
)
where
import Graphics.Vty
import Graphics.Vty.DisplayAttributes
import Graphics.Vty.Inline.Unsafe
import Blaze.ByteString.Builder (writeToByteString)
import Control.Monad.State.Strict
import Data.Bits ( (.&.), complement )
import Data.IORef
import System.IO
type InlineM v = State InlineState v
data InlineState =
InlineState { InlineState -> Attr
inlineAttr :: Attr
, InlineState -> Bool
inlineUrlsEnabled :: Bool
}
backColor :: Color -> InlineM ()
backColor :: Color -> InlineM ()
backColor Color
c = (InlineState -> InlineState) -> InlineM ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((InlineState -> InlineState) -> InlineM ())
-> (InlineState -> InlineState) -> InlineM ()
forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr = InlineState -> Attr
inlineAttr InlineState
s Attr -> Attr -> Attr
forall a. Monoid a => a -> a -> a
`mappend` (Attr
currentAttr Attr -> Color -> Attr
`withBackColor` Color
c)
}
foreColor :: Color -> InlineM ()
foreColor :: Color -> InlineM ()
foreColor Color
c = (InlineState -> InlineState) -> InlineM ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((InlineState -> InlineState) -> InlineM ())
-> (InlineState -> InlineState) -> InlineM ()
forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr = InlineState -> Attr
inlineAttr InlineState
s Attr -> Attr -> Attr
forall a. Monoid a => a -> a -> a
`mappend` (Attr
currentAttr Attr -> Color -> Attr
`withForeColor` Color
c)
}
applyStyle :: Style -> InlineM ()
applyStyle :: Style -> InlineM ()
applyStyle Style
st = (InlineState -> InlineState) -> InlineM ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((InlineState -> InlineState) -> InlineM ())
-> (InlineState -> InlineState) -> InlineM ()
forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr = InlineState -> Attr
inlineAttr InlineState
s Attr -> Attr -> Attr
forall a. Monoid a => a -> a -> a
`mappend` (Attr
currentAttr Attr -> Style -> Attr
`withStyle` Style
st)
}
removeStyle :: Style -> InlineM ()
removeStyle :: Style -> InlineM ()
removeStyle Style
sMask = (InlineState -> InlineState) -> InlineM ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((InlineState -> InlineState) -> InlineM ())
-> (InlineState -> InlineState) -> InlineM ()
forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr =
let style' :: Style
style' = case Attr -> MaybeDefault Style
attrStyle (InlineState -> Attr
inlineAttr InlineState
s) of
MaybeDefault Style
Default -> [Char] -> Style
forall a. HasCallStack => [Char] -> a
error ([Char] -> Style) -> [Char] -> Style
forall a b. (a -> b) -> a -> b
$ [Char]
"Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
MaybeDefault Style
KeepCurrent -> [Char] -> Style
forall a. HasCallStack => [Char] -> a
error ([Char] -> Style) -> [Char] -> Style
forall a b. (a -> b) -> a -> b
$ [Char]
"Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
SetTo Style
st -> Style
st Style -> Style -> Style
forall a. Bits a => a -> a -> a
.&. Style -> Style
forall a. Bits a => a -> a
complement Style
sMask
in (InlineState -> Attr
inlineAttr InlineState
s) { attrStyle :: MaybeDefault Style
attrStyle = Style -> MaybeDefault Style
forall v. (Eq v, Show v, Read v) => v -> MaybeDefault v
SetTo Style
style' }
}
defaultAll :: InlineM ()
defaultAll :: InlineM ()
defaultAll = (InlineState -> InlineState) -> InlineM ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((InlineState -> InlineState) -> InlineM ())
-> (InlineState -> InlineState) -> InlineM ()
forall a b. (a -> b) -> a -> b
$ \InlineState
s -> InlineState
s { inlineAttr :: Attr
inlineAttr = Attr
defAttr }
putAttrChange :: ( Applicative m, MonadIO m ) => Output -> InlineM () -> m ()
putAttrChange :: Output -> InlineM () -> m ()
putAttrChange Output
out InlineM ()
c = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
DisplayRegion
bounds <- Output -> IO DisplayRegion
displayBounds Output
out
DisplayContext
dc <- Output -> DisplayRegion -> IO DisplayContext
displayContext Output
out DisplayRegion
bounds
Maybe FixedAttr
mfattr <- AssumedState -> Maybe FixedAttr
prevFattr (AssumedState -> Maybe FixedAttr)
-> IO AssumedState -> IO (Maybe FixedAttr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef AssumedState -> IO AssumedState
forall a. IORef a -> IO a
readIORef (Output -> IORef AssumedState
assumedStateRef Output
out)
FixedAttr
fattr <- case Maybe FixedAttr
mfattr of
Maybe FixedAttr
Nothing -> do
IO () -> IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Output -> ByteString -> IO ()
outputByteBuffer Output
out (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Write -> ByteString
writeToByteString (Write -> ByteString) -> Write -> ByteString
forall a b. (a -> b) -> a -> b
$ DisplayContext -> Bool -> Write
writeDefaultAttr DisplayContext
dc Bool
False
FixedAttr -> IO FixedAttr
forall (m :: * -> *) a. Monad m => a -> m a
return (FixedAttr -> IO FixedAttr) -> FixedAttr -> IO FixedAttr
forall a b. (a -> b) -> a -> b
$ Style -> Maybe Color -> Maybe Color -> Maybe Text -> FixedAttr
FixedAttr Style
defaultStyleMask Maybe Color
forall a. Maybe a
Nothing Maybe Color
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
Just FixedAttr
v -> FixedAttr -> IO FixedAttr
forall (m :: * -> *) a. Monad m => a -> m a
return FixedAttr
v
let InlineState Attr
attr Bool
urlsEnabled = InlineM () -> InlineState -> InlineState
forall s a. State s a -> s -> s
execState InlineM ()
c (Attr -> Bool -> InlineState
InlineState Attr
currentAttr Bool
False)
attr' :: Attr
attr' = Output -> Attr -> Attr
limitAttrForDisplay Output
out Attr
attr
fattr' :: FixedAttr
fattr' = FixedAttr -> Attr -> FixedAttr
fixDisplayAttr FixedAttr
fattr Attr
attr'
diffs :: DisplayAttrDiff
diffs = FixedAttr -> FixedAttr -> DisplayAttrDiff
displayAttrDiffs FixedAttr
fattr FixedAttr
fattr'
Output -> ByteString -> IO ()
outputByteBuffer Output
out (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Write -> ByteString
writeToByteString (Write -> ByteString) -> Write -> ByteString
forall a b. (a -> b) -> a -> b
$ DisplayContext
-> Bool -> FixedAttr -> Attr -> DisplayAttrDiff -> Write
writeSetAttr DisplayContext
dc Bool
urlsEnabled FixedAttr
fattr Attr
attr' DisplayAttrDiff
diffs
IORef AssumedState -> (AssumedState -> AssumedState) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef (Output -> IORef AssumedState
assumedStateRef Output
out) ((AssumedState -> AssumedState) -> IO ())
-> (AssumedState -> AssumedState) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AssumedState
s -> AssumedState
s { prevFattr :: Maybe FixedAttr
prevFattr = FixedAttr -> Maybe FixedAttr
forall a. a -> Maybe a
Just FixedAttr
fattr' }
DisplayContext -> IO ()
inlineHack DisplayContext
dc
putAttrChange_ :: ( Applicative m, MonadIO m ) => InlineM () -> m ()
putAttrChange_ :: InlineM () -> m ()
putAttrChange_ InlineM ()
c = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ (Output -> IO ()) -> IO ()
forall b. (Output -> IO b) -> IO b
withOutput ((Output -> IO ()) -> IO ()) -> (Output -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Output
out -> do
Handle -> IO ()
hFlush Handle
stdout
Output -> InlineM () -> IO ()
forall (m :: * -> *).
(Applicative m, MonadIO m) =>
Output -> InlineM () -> m ()
putAttrChange Output
out InlineM ()
c
Handle -> IO ()
hFlush Handle
stdout