prettyprinter-graphviz-1.1.0.0: src/Prettyprinter/Render/GraphViz.hs
-- | Pretty-print GraphViz labels
module Prettyprinter.Render.GraphViz (
render,
render',
) where
import qualified Data.Text.Lazy as TL
import qualified Data.Text as T
import Data.GraphViz.Attributes.Complete (Label(HtmlLabel))
import qualified Data.GraphViz.Attributes.HTML as H
import Data.Text.Prettyprint.Doc (
Doc,
SimpleDocStream(
SFail,
SEmpty,
SChar,
SText,
SLine,
SAnnPush,
SAnnPop),
layoutPretty, defaultLayoutOptions,
)
import Data.Text.Prettyprint.Doc.Internal (textSpaces)
import Data.Text.Prettyprint.Doc.Render.Util.Panic (
panicUnpairedPop, panicInputNotFullyConsumed, panicUncaughtFail
)
-- | Render a document as a GraphViz label, using sensible defaults.
render :: Doc H.Attributes -> Label
render = HtmlLabel . H.Text . render' . layoutPretty defaultLayoutOptions
-- | Render a document stream as HTML text for GraphViz. This provides more fine-grained control than 'render'.
render' :: SimpleDocStream H.Attributes -> H.Text
render' = renderSimplyDecorated' mempty mempty
{- Util -}
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = (.) . (.)
-- | This is a minor modification of 'renderSimplyDecorated', where the /text/ function is
-- additionally passed the current stack.
renderSimplyDecorated' :: ([H.Attribute] -> [H.TextItem]) -> ([H.Attribute] -> [H.TextItem]) -> SimpleDocStream [H.Attribute] -> [H.TextItem]
renderSimplyDecorated' push pop = go []
where
text = pure .: (renderText . concat)
go _ SFail = panicUncaughtFail
go [] SEmpty = mempty
go (_:_) SEmpty = panicInputNotFullyConsumed
go stack (SChar c rest) = text stack (T.singleton c) <> go stack rest
go stack (SText _l t rest) = text stack t <> go stack rest
go stack (SLine i rest) = [H.Newline [H.Align H.HLeft]] <> text stack (textSpaces i) <> go stack rest
go stack (SAnnPush ann rest) = push ann <> go (ann : stack) rest
go (ann:stack) (SAnnPop rest) = pop ann <> go stack rest
go [] SAnnPop{} = panicUnpairedPop
-- | Helper for rendering an individual 'H.TextItem'.
renderText :: H.Attributes -> T.Text -> H.TextItem
renderText cs t
| T.null t = ti -- graphviz doesn't like an empty string between tags
| otherwise = H.Font cs [ti]
where ti = H.Str $ TL.fromStrict t