{-# language NoImplicitPrelude, DoAndIfThenElse, OverloadedStrings, ExtendedDefaultRules #-}
module IHaskell.Publish
( publishResult
) where
import IHaskellPrelude
import qualified Data.Text as T
import qualified Data.Time as Time
import IHaskell.Display
import IHaskell.Types
import IHaskell.CSS (ihaskellCSS)
publishResult :: (Message -> IO ())
-> MessageHeader
-> MVar [Display]
-> MVar Bool
-> MVar [DisplayData]
-> Bool
-> EvaluationResult
-> ErrorOccurred
-> IO ()
publishResult :: (Message -> IO ())
-> MessageHeader
-> MVar [Display]
-> MVar Bool
-> MVar [DisplayData]
-> Bool
-> EvaluationResult
-> ErrorOccurred
-> IO ()
publishResult Message -> IO ()
send MessageHeader
replyHeader MVar [Display]
displayed MVar Bool
updateNeeded MVar [DisplayData]
poutput Bool
upager EvaluationResult
result ErrorOccurred
success = do
let final :: Bool
final =
case EvaluationResult
result of
IntermediateResult{} -> Bool
False
FinalResult{} -> Bool
True
outs :: Display
outs = EvaluationResult -> Display
evaluationOutputs EvaluationResult
result
Text
uniqueLabel <- IO Text
getUniqueLabel
Bool
clear <- forall a. MVar a -> IO a
readMVar MVar Bool
updateNeeded
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
clear forall a b. (a -> b) -> a -> b
$ do
IO ()
clearOutput
[Display]
disps <- forall a. MVar a -> IO a
readMVar MVar [Display]
displayed
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Text -> Display -> IO ()
sendOutput Text
uniqueLabel) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [Display]
disps
Text -> Display -> IO ()
sendOutput Text
uniqueLabel Display
outs
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar Bool
updateNeeded (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not Bool
final)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
final forall a b. (a -> b) -> a -> b
$ do
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar [Display]
displayed (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Display
outs forall a. a -> [a] -> [a]
:))
case EvaluationResult
result of
IntermediateResult Display
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
FinalResult Display
_ [DisplayData]
pager [WidgetMsg]
_ ->
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [DisplayData]
pager) forall a b. (a -> b) -> a -> b
$
if Bool
upager
then forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar [DisplayData]
poutput (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. [a] -> [a] -> [a]
++ [DisplayData]
pager))
else Text -> Display -> IO ()
sendOutput Text
uniqueLabel forall a b. (a -> b) -> a -> b
$ [DisplayData] -> Display
Display [DisplayData]
pager
where
clearOutput :: IO ()
clearOutput = do
MessageHeader
hdr <- MessageHeader -> MessageType -> IO MessageHeader
dupHeader MessageHeader
replyHeader MessageType
ClearOutputMessage
Message -> IO ()
send forall a b. (a -> b) -> a -> b
$ MessageHeader -> Bool -> Message
ClearOutput MessageHeader
hdr Bool
True
sendOutput :: Text -> Display -> IO ()
sendOutput Text
uniqueLabel (ManyDisplay [Display]
manyOuts) =
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Text -> Display -> IO ()
sendOutput Text
uniqueLabel) [Display]
manyOuts
sendOutput Text
uniqueLabel (Display [DisplayData]
outs) = case ErrorOccurred
success of
ErrorOccurred
Success -> do
MessageHeader
hdr <- MessageHeader -> MessageType -> IO MessageHeader
dupHeader MessageHeader
replyHeader MessageType
DisplayDataMessage
Message -> IO ()
send forall a b. (a -> b) -> a -> b
$ MessageHeader -> [DisplayData] -> Maybe Transient -> Message
PublishDisplayData MessageHeader
hdr (forall a b. (a -> b) -> [a] -> [b]
map (Text -> DisplayData -> DisplayData
makeUnique Text
uniqueLabel forall b c a. (b -> c) -> (a -> b) -> a -> c
. DisplayData -> DisplayData
prependCss) [DisplayData]
outs) forall a. Maybe a
Nothing
ErrorOccurred
Failure -> do
MessageHeader
hdr <- MessageHeader -> MessageType -> IO MessageHeader
dupHeader MessageHeader
replyHeader MessageType
ExecuteErrorMessage
Message -> IO ()
send forall a b. (a -> b) -> a -> b
$ MessageHeader -> [Text] -> Text -> Text -> Message
ExecuteError MessageHeader
hdr [String -> Text
T.pack ([DisplayData] -> String
extractPlain [DisplayData]
outs)] Text
"" Text
""
prependCss :: DisplayData -> DisplayData
prependCss (DisplayData MimeType
MimeHtml Text
h) =
MimeType -> Text -> DisplayData
DisplayData MimeType
MimeHtml forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat [Text
"<style>", String -> Text
T.pack String
ihaskellCSS, Text
"</style>", Text
h]
prependCss DisplayData
x = DisplayData
x
makeUnique :: Text -> DisplayData -> DisplayData
makeUnique Text
l (DisplayData MimeType
MimeSvg Text
s) =
MimeType -> Text -> DisplayData
DisplayData MimeType
MimeSvg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"glyph" (Text
"glyph-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"\"clip" (Text
"\"clip-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"#clip" (Text
"#clip-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"\"image" (Text
"\"image-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"#image" (Text
"#image-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"linearGradient id=\"linear" (Text
"linearGradient id=\"linear-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"#linear" (Text
"#linear-" forall a. Semigroup a => a -> a -> a
<> Text
l)
forall a b. (a -> b) -> a -> b
$ Text
s
makeUnique Text
_ DisplayData
x = DisplayData
x
getUniqueLabel :: IO Text
getUniqueLabel =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Time.UTCTime Day
d DiffTime
s) -> String -> Text
T.pack (forall a. Show a => a -> String
show Day
d) forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (forall a. Show a => a -> String
show DiffTime
s))
IO UTCTime
Time.getCurrentTime