{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Ghci.Websockets.Simple ( -- $docs broadcastText , broadcastHtml , broadcastPlot -- * Re-exports etc. , Message(..) , module Websockets ) where import Data.Aeson import Data.Text (Text) import qualified Data.Text as Text import Ghci.Websockets as Websockets -- $docs -- This module provides the 'Message' data type, and various constructors for -- it. It is intended to be used together with the 'html/index.html' file. -- -- = Usage -- -- 1. Start a GHCi session and run 'Ghci.Websockets.initialiseDef' -- 2. Open @html/index.html@ in a browser (it's self-contained, no http server -- required) -- 3. Use 'broadcastText', 'broadcastHtml' and 'broadcastPlot' to show things -- in the browser window. data Message = MsgText Text.Text -- ^ A string | MsgHtml Text.Text -- ^ An HTML fragment | MsgPlotly [Value] Value -- ^ The 'data' and 'layout' parameters used for 'Plotly.newPlot' -- (see -- https://plot.ly/javascript/plotlyjs-function-reference/#plotlynewplot). -- The first parameter is a list of Plotly traces (See -- https://plot.ly/javascript/reference/, -- "Trace types"), the second parameter is a Plotly layout value (see -- https://plot.ly/javascript/reference/, "Layout") instance ToJSON Message where toJSON = \case MsgText t -> object ["tag" .= ("text" :: String), "contents" .= t] MsgHtml t -> object ["tag" .= ("html" :: String), "contents" .= t] MsgPlotly dt ly -> object ["tag" .= ("plot" :: String), "contents" .= object ["data" .= dt, "layout" .= ly]] -- | Show a string. -- -- >>> broadcastText "hello" -- broadcastText :: Text -> IO () broadcastText = broadcast . MsgText -- | Insert some HTML into the DOM. -- -- >>> broadcastHtml "

Hello

" -- broadcastHtml :: Text -> IO () broadcastHtml = broadcast . MsgHtml -- | Show a Plotly 2D line plot of the given points. -- -- >>> broadcastPlot [(1, 2), (2, 5), (3, 4), (4, 3)] -- -- >>> broadcastPlot $ fmap (\i -> let i' = (fromIntegral i / 10) in (i', sin i')) [1..100] -- broadcastPlot :: [(Double, Double)] -> IO () broadcastPlot ns = broadcast (MsgPlotly [dt] ly) where ly = object ["margin" .= object ["t" .= (0 :: Int)]] dt = let (xs, ys) = unzip ns in object [ "x" .= xs, "y" .= ys ]