graphwiz 1.0.0 → 2.0.0
raw patch · 9 files changed
+54/−127 lines, 9 filesdep ~textdep ~text-builderPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: text, text-builder
API changes (from Hackage documentation)
- Text.Dot: digraph :: Dot a -> Builder
+ Text.Dot: digraph :: Dot a -> TextBuilder
- Text.Dot: digraphT :: Monad m => DotT m a -> m Builder
+ Text.Dot: digraphT :: Monad m => DotT m a -> m TextBuilder
- Text.Dot: digraphWith :: (Entity -> Dot a) -> Builder
+ Text.Dot: digraphWith :: (Entity -> Dot a) -> TextBuilder
- Text.Dot: digraphWithT :: Monad m => (Entity -> DotT m a) -> m Builder
+ Text.Dot: digraphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder
- Text.Dot: graph :: Dot a -> Builder
+ Text.Dot: graph :: Dot a -> TextBuilder
- Text.Dot: graphT :: Monad m => DotT m a -> m Builder
+ Text.Dot: graphT :: Monad m => DotT m a -> m TextBuilder
- Text.Dot: graphWith :: (Entity -> Dot a) -> Builder
+ Text.Dot: graphWith :: (Entity -> Dot a) -> TextBuilder
- Text.Dot: graphWithT :: Monad m => (Entity -> DotT m a) -> m Builder
+ Text.Dot: graphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder
- Text.Dot: strictDigraph :: Dot a -> Builder
+ Text.Dot: strictDigraph :: Dot a -> TextBuilder
- Text.Dot: strictDigraphT :: Monad m => DotT m a -> m Builder
+ Text.Dot: strictDigraphT :: Monad m => DotT m a -> m TextBuilder
- Text.Dot: strictDigraphWith :: (Entity -> Dot a) -> Builder
+ Text.Dot: strictDigraphWith :: (Entity -> Dot a) -> TextBuilder
- Text.Dot: strictDigraphWithT :: Monad m => (Entity -> DotT m a) -> m Builder
+ Text.Dot: strictDigraphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder
- Text.Dot: strictGraph :: Dot a -> Builder
+ Text.Dot: strictGraph :: Dot a -> TextBuilder
- Text.Dot: strictGraphT :: Monad m => DotT m a -> m Builder
+ Text.Dot: strictGraphT :: Monad m => DotT m a -> m TextBuilder
- Text.Dot: strictGraphWith :: (Entity -> Dot a) -> Builder
+ Text.Dot: strictGraphWith :: (Entity -> Dot a) -> TextBuilder
- Text.Dot: strictGraphWithT :: Monad m => (Entity -> DotT m a) -> m Builder
+ Text.Dot: strictGraphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder
Files
- CHANGELOG.md +4/−0
- README.md +2/−2
- common/Prelude.hs +1/−82
- example/Main.hs +3/−2
- graphwiz.cabal +3/−2
- src/Text/Dot.hs +2/−2
- src/Text/Dot/Render.hs +31/−30
- test/Golden.hs +5/−4
- test/Reporter.hs +3/−3
CHANGELOG.md view
@@ -1,3 +1,7 @@ 1.0.0 ----- * First version++2.0.0+-----+* Upgrade text-builder to 1.0
README.md view
@@ -46,9 +46,9 @@ liftIO $ print =<< use (attributes x) ``` -### Text.Builder+### TextBuilder -For efficiency and convenience, the result of running the `Dot` monad is not a `String` or `Text`; it's a [Text.Builder](https://hackage.haskell.org/package/text-builder-0.6.7.3/docs/Text-Builder.html), that can be converted to a strict `Text` or even printed directly to the standard output.+For efficiency and convenience, the result of running the `Dot` monad is not a `String` or `Text`; it's a [TextBuilder](https://hackage.haskell.org/package/text-builder-1.0.0.4/docs/TextBuilder.html), that can be converted to a strict `Text` or even printed directly to the standard output. ### Auto compound
common/Prelude.hs view
@@ -1,6 +1,3 @@-{-# OPTIONS_GHC -Wno-orphans #-}-{-# LANGUAGE PatternSynonyms #-}- {- | Internal module that re-exports the regular prelude, plus some common useful@@ -8,23 +5,7 @@ -} -module Prelude- ( -- * re-exports from useful "default" modules- module P- -- * custom operators- , (...)- -- * maybe helpers- , onNothing- , onNothingM- -- * either helpers- , onLeft- , onLeftM- -- * sequence helpers- , Seq (.., Lone)- -- * hashmap helpers- , unionWithM- , unionWithKeyM- ) where+module Prelude (module P) where -- re-exports@@ -65,65 +46,3 @@ import Data.Void as P (Void, absurd) import GHC.Generics as P (Generic) import "base" Prelude as P hiding (lookup)----- internal imports--import Data.HashMap.Strict qualified as M-import Data.Sequence (Seq (..))----- operators--(...) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)-f ... g = \x y -> f (g x y)-infixr 8 ...----- maybe helpers--onNothing :: Applicative m => Maybe a -> m a -> m a-onNothing a d = maybe d pure a--onNothingM :: Monad m => m (Maybe a) -> m a -> m a-onNothingM a d = a >>= flip onNothing d----- either helpers--onLeft :: Applicative m => Either e a -> (e -> m a) -> m a-onLeft a f = either f pure a--onLeftM :: Monad m => m (Either e a) -> (e -> m a) -> m a-onLeftM a f = a >>= flip onLeft f----- sequence helpers--pattern Lone :: a -> Seq a-pattern Lone x = x :<| Empty----- hashmap helpers--unionWithM ::- (Monad m, Hashable k) =>- (v -> v -> m v) ->- HashMap k v ->- HashMap k v ->- m (HashMap k v)-unionWithM = unionWithKeyM . const--unionWithKeyM ::- (Monad m, Hashable k) =>- (k -> v -> v -> m v) ->- HashMap k v ->- HashMap k v ->- m (HashMap k v)-unionWithKeyM f m1 m2 = foldM step m1 (M.toList m2)- where- step m (k, new) = case M.lookup k m of- Nothing -> pure $ M.insert k new m- Just old -> do- combined <- f k new old- pure $ M.insert k combined m
example/Main.hs view
@@ -1,12 +1,13 @@ module Main where import Control.Lens-import Text.Builder qualified as TB+import Data.Text.IO qualified as T import Text.Dot+import TextBuilder qualified as TB main :: IO () main =- TB.putLnToStdOut $+ T.putStrLn $ TB.toText $ digraph do defaults Node . style ?= "filled"
graphwiz.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.4 name: graphwiz synopsis: Monadic DOT graph builder DSL-version: 1.0.0+version: 2.0.0 category: Data, Text license: BSD-3-Clause license-file: LICENSE@@ -90,7 +90,7 @@ , lens >=5 && <6 , mtl >=2 && <3 , text >=2 && <3- , text-builder <1+ , text-builder >=1 && <2 , transformers <1 , unordered-containers <1 @@ -134,4 +134,5 @@ , base , graphwiz , lens+ , text , text-builder
src/Text/Dot.hs view
@@ -10,8 +10,8 @@ functions to create one of the four graph [entities](#g:entities). Their attributes can be set via lenses such as '?=', see [attributes](#g:attributes). -The output is a 'Text.Builder.Builder', that you can convert to a strict-'Data.Text.Text' or print directly.+The output is a 'TextBuilder.TextBuilder', that you can convert to a+strict 'Data.Text.Text' or print directly. -}
src/Text/Dot/Render.hs view
@@ -21,9 +21,9 @@ import Data.HashMap.Strict qualified as M import Data.List.NonEmpty qualified as NE-import Text.Builder (Builder)-import Text.Builder qualified as TB import Text.Printf+import TextBuilder (TextBuilder)+import TextBuilder qualified as TB import Text.Dot.Monad import Text.Dot.Types@@ -36,131 +36,132 @@ -- -- Given a t'DotT' expression that builds a graph, this function evaluates it -- and builds an undirected non-strict graph. It returns the result in the--- underlying monad, as a 'Builder'. The callback takes the graph's identifier--- as argument.+-- underlying monad, as a 'TextBuilder'. The callback takes the graph's+-- identifier as argument. -- -- The result of the graph building expression itself is ignored.-graphWithT :: Monad m => (Entity -> DotT m a) -> m Builder+graphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder graphWithT = render "graph" "--" -- | Renders a given graph. -- -- Like 'graphWithT', but the expression doesn't take the identifier as agument.-graphT :: Monad m => DotT m a -> m Builder+graphT :: Monad m => DotT m a -> m TextBuilder graphT = render "graph" "--" . const -- | Renders a given graph. -- -- Like 'graphWithT', but in the 'Dot' monad.-graphWith :: (Entity -> Dot a) -> Builder+graphWith :: (Entity -> Dot a) -> TextBuilder graphWith = runIdentity . render "graph" "--" -- | Renders a given graph. -- -- Like 'graphT', but in the 'Dot' monad.-graph :: Dot a -> Builder+graph :: Dot a -> TextBuilder graph = runIdentity . render "graph" "--" . const -- | Renders a given graph. -- -- Given a t'DotT' expression that builds a graph, this function evaluates it -- and builds a directed non-strict graph. It returns the result in the--- underlying monad, as a 'Builder'. The callback takes the graph's identifier--- as argument.+-- underlying monad, as a 'TextBuilder'. The callback takes the graph's+-- identifier as argument. -- -- The result of the graph building expression itself is ignored.-digraphWithT :: Monad m => (Entity -> DotT m a) -> m Builder+digraphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder digraphWithT = render "digraph" "->" -- | Renders a given graph. -- -- Like 'digraphWithT', but the expression doesn't take the entity as agument.-digraphT :: Monad m => DotT m a -> m Builder+digraphT :: Monad m => DotT m a -> m TextBuilder digraphT = render "digraph" "->" . const -- | Renders a given graph. -- -- Like 'digraphWithT', but in the 'Dot' monad.-digraphWith :: (Entity -> Dot a) -> Builder+digraphWith :: (Entity -> Dot a) -> TextBuilder digraphWith = runIdentity . render "digraph" "->" -- | Renders a given graph. -- -- Like 'digraphT', but in the 'Dot' monad.-digraph :: Dot a -> Builder+digraph :: Dot a -> TextBuilder digraph = runIdentity . render "digraph" "->" . const -- | Renders a given graph. -- -- Given a t'DotT' expression that builds a graph, this function evaluates it -- and builds an undirected strict graph. It returns the result in the--- underlying monad, as a 'Builder'. The callback takes the graph's identifier--- as argument.+-- underlying monad, as a 'TextBuilder'. The callback takes the graph's+-- identifier as argument. -- -- The result of the graph building expression itself is ignored.-strictGraphWithT :: Monad m => (Entity -> DotT m a) -> m Builder+strictGraphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder strictGraphWithT = render "strict graph" "--" -- | Renders a given graph. -- -- Like 'strictGraphWithT', but the expression doesn't take the entity as agument.-strictGraphT :: Monad m => DotT m a -> m Builder+strictGraphT :: Monad m => DotT m a -> m TextBuilder strictGraphT = render "strict graph" "--" . const -- | Renders a given graph. -- -- Like 'strictGraphWithT', but in the 'Dot' monad.-strictGraphWith :: (Entity -> Dot a) -> Builder+strictGraphWith :: (Entity -> Dot a) -> TextBuilder strictGraphWith = runIdentity . render "strict graph" "--" -- | Renders a given graph. -- -- Like 'strictGraphT', but in the 'Dot' monad.-strictGraph :: Dot a -> Builder+strictGraph :: Dot a -> TextBuilder strictGraph = runIdentity . render "strict graph" "--" . const -- | Renders a given graph. -- -- Given a t'DotT' expression that builds a graph, this function evaluates it -- and builds a directed strict graph. It returns the result in the underlying--- monad, as a 'Builder'. The callback takes the graph's identifier as argument.+-- monad, as a 'TextBuilder'. The callback takes the graph's identifier as+-- argument. -- -- The result of the graph building expression itself is ignored.-strictDigraphWithT :: Monad m => (Entity -> DotT m a) -> m Builder+strictDigraphWithT :: Monad m => (Entity -> DotT m a) -> m TextBuilder strictDigraphWithT = render "strict digraph" "->" -- | Renders a given graph. -- -- Like 'strictDigraphWithT', but the expression doesn't take the entity as agument.-strictDigraphT :: Monad m => DotT m a -> m Builder+strictDigraphT :: Monad m => DotT m a -> m TextBuilder strictDigraphT = render "strict digraph" "->" . const -- | Renders a given graph. -- -- Like 'strictDigraphWithT', but in the 'Dot' monad.-strictDigraphWith :: (Entity -> Dot a) -> Builder+strictDigraphWith :: (Entity -> Dot a) -> TextBuilder strictDigraphWith = runIdentity . render "strict digraph" "->" -- | Renders a given graph. -- -- Like 'strictDigraphT', but in the 'Dot' monad.-strictDigraph :: Dot a -> Builder+strictDigraph :: Dot a -> TextBuilder strictDigraph = runIdentity . render "strict digraph" "->" . const -------------------------------------------------------------------------------- -- Internal helpers -render :: Monad m => Builder -> Builder -> (Entity -> DotT m a) -> m Builder+render :: Monad m => TextBuilder -> TextBuilder -> (Entity -> DotT m a) -> m TextBuilder render gtype arrow f = do let root = Entity Subgraph (-1) allGraph <- run root (f root) pure $ TB.intercalate "\n" $ visit allGraph gtype arrow root -indent :: [Builder] -> [Builder]+indent :: [TextBuilder] -> [TextBuilder] indent = map (" " <>) -visit :: DotGraph -> Builder -> Builder -> Entity -> [Builder]+visit :: DotGraph -> TextBuilder -> TextBuilder -> Entity -> [TextBuilder] visit DotGraph {..} gtype arrow = visitGraph where magnitude = ceiling (logBase 10 (fromIntegral _entityIndex :: Double)) :: Int@@ -209,8 +210,8 @@ , renderIndex p2 , " [" , TB.intercalate "," $ visitAttributes $ attrs- <> M.fromList [("ltail", TB.run $ renderIndex o1) | getType o1 == Cluster]- <> M.fromList [("lhead", TB.run $ renderIndex o2) | getType o2 == Cluster]+ <> M.fromList [("ltail", TB.toText $ renderIndex o1) | getType o1 == Cluster]+ <> M.fromList [("lhead", TB.toText $ renderIndex o2) | getType o2 == Cluster] , "]" ]
test/Golden.hs view
@@ -12,14 +12,15 @@ import System.FilePath import Test.Tasty import Test.Tasty.Golden-import Text.Builder qualified as TB import Text.Dot+import TextBuilder (TextBuilder)+import TextBuilder qualified as TB -go :: String -> TB.Builder -> TestTree+go :: String -> TextBuilder -> TestTree go testname = goldenVsString testname filename . pure . builderToBytestring where filename = "test" </> "golden" </> intercalate "_" (words testname) <> ".dot"- builderToBytestring = T.encodeUtf8 . T.fromStrict . TB.run . (<> "\n")+ builderToBytestring = T.encodeUtf8 . T.fromStrict . TB.toText . (<> "\n") test = go "simple graph" $@@ -116,4 +117,4 @@ path <- sequence do eid <- toList entityStack pure $ use $ attributes eid . label- node $ TB.run $ TB.intercalate " > " $ reverse $ map TB.text $ catMaybes path+ node $ TB.toText $ TB.intercalate " > " $ reverse $ map TB.text $ catMaybes path
test/Reporter.hs view
@@ -15,7 +15,7 @@ import Test.Tasty.Options import Test.Tasty.Providers import Test.Tasty.Runners-import Text.Builder qualified as TB+import TextBuilder qualified as TB -- custom CI reporter@@ -97,8 +97,8 @@ , TB.text desc , "</td></tr>" ] <> "\n"- T.writeFile summaryFile $ TB.run ("| " <> summary <> " |\n")- T.writeFile failingFile $ TB.run failing+ T.writeFile summaryFile $ TB.toText ("| " <> summary <> " |\n")+ T.writeFile failingFile $ TB.toText failing pure $ failure == 0 customFold :: StatusMap -> TreeFold (FoldMonad IO [([Text], Maybe Text)])