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 = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr = InlineState -> Attr
inlineAttr InlineState
s Attr -> Color -> Attr
`withBackColor` Color
c
}
foreColor :: Color -> InlineM ()
foreColor :: Color -> InlineM ()
foreColor Color
c = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr = InlineState -> Attr
inlineAttr InlineState
s Attr -> Color -> Attr
`withForeColor` Color
c
}
applyStyle :: Style -> InlineM ()
applyStyle :: Style -> InlineM ()
applyStyle Style
st = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify forall a b. (a -> b) -> a -> b
$ \InlineState
s ->
InlineState
s { inlineAttr :: Attr
inlineAttr = InlineState -> Attr
inlineAttr InlineState
s Attr -> Style -> Attr
`withStyle` Style
st
}
removeStyle :: Style -> InlineM ()
removeStyle :: Style -> InlineM ()
removeStyle Style
sMask = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify 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 -> forall a. HasCallStack => [Char] -> a
error [Char]
"Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
MaybeDefault Style
KeepCurrent -> forall a. HasCallStack => [Char] -> a
error [Char]
"Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
SetTo Style
st -> Style
st forall a. Bits a => a -> a -> a
.&. forall a. Bits a => a -> a
complement Style
sMask
in (InlineState -> Attr
inlineAttr InlineState
s) { attrStyle :: MaybeDefault Style
attrStyle = forall v. v -> MaybeDefault v
SetTo Style
style' }
}
defaultAll :: InlineM ()
defaultAll :: InlineM ()
defaultAll = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify 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 :: forall (m :: * -> *).
(Applicative m, MonadIO m) =>
Output -> InlineM () -> m ()
putAttrChange Output
out InlineM ()
c = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO 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 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. IORef a -> IO a
readIORef (Output -> IORef AssumedState
assumedStateRef Output
out)
FixedAttr
fattr <- case Maybe FixedAttr
mfattr of
Maybe FixedAttr
Nothing -> do
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Output -> ByteString -> IO ()
outputByteBuffer Output
out forall a b. (a -> b) -> a -> b
$ Write -> ByteString
writeToByteString forall a b. (a -> b) -> a -> b
$ DisplayContext -> Bool -> Write
writeDefaultAttr DisplayContext
dc Bool
False
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Style -> Maybe Color -> Maybe Color -> Maybe Text -> FixedAttr
FixedAttr Style
defaultStyleMask forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall a. Maybe a
Nothing
Just FixedAttr
v -> forall (m :: * -> *) a. Monad m => a -> m a
return FixedAttr
v
let InlineState Attr
attr Bool
urlsEnabled = 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 forall a b. (a -> b) -> a -> b
$ Write -> ByteString
writeToByteString forall a b. (a -> b) -> a -> b
$ DisplayContext
-> Bool -> FixedAttr -> Attr -> DisplayAttrDiff -> Write
writeSetAttr DisplayContext
dc Bool
urlsEnabled FixedAttr
fattr Attr
attr' DisplayAttrDiff
diffs
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef (Output -> IORef AssumedState
assumedStateRef Output
out) forall a b. (a -> b) -> a -> b
$ \AssumedState
s -> AssumedState
s { prevFattr :: Maybe FixedAttr
prevFattr = forall a. a -> Maybe a
Just FixedAttr
fattr' }
DisplayContext -> IO ()
inlineHack DisplayContext
dc
putAttrChange_ :: ( Applicative m, MonadIO m ) => InlineM () -> m ()
putAttrChange_ :: forall (m :: * -> *).
(Applicative m, MonadIO m) =>
InlineM () -> m ()
putAttrChange_ InlineM ()
c = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall b. (Output -> IO b) -> IO b
withOutput forall a b. (a -> b) -> a -> b
$ \Output
out -> do
Handle -> IO ()
hFlush Handle
stdout
forall (m :: * -> *).
(Applicative m, MonadIO m) =>
Output -> InlineM () -> m ()
putAttrChange Output
out InlineM ()
c
Handle -> IO ()
hFlush Handle
stdout