graphviz 2999.16.0.0 → 2999.17.0.0
raw patch · 39 files changed
+5245/−4729 lines, 39 filesdep ~QuickCheckdep ~basedep ~colournew-component:exe:graphviz-testparsingPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: QuickCheck, base, colour, criterion, dlist, fgl, polyparse, temporary, transformers, wl-pprint-text
API changes (from Hackage documentation)
- Data.GraphViz.Attributes.Complete: Aspect :: AspectType -> Attribute
- Data.GraphViz.Attributes.Complete: RatioOnly :: Double -> AspectType
- Data.GraphViz.Attributes.Complete: RatioPassCount :: Double -> Int -> AspectType
- Data.GraphViz.Attributes.Complete: data AspectType
- Data.GraphViz.Attributes.Complete: instance Bounded ArrowFill
- Data.GraphViz.Attributes.Complete: instance Bounded ArrowShape
- Data.GraphViz.Attributes.Complete: instance Bounded ArrowSide
- Data.GraphViz.Attributes.Complete: instance Bounded ClusterMode
- Data.GraphViz.Attributes.Complete: instance Bounded DEConstraints
- Data.GraphViz.Attributes.Complete: instance Bounded DirType
- Data.GraphViz.Attributes.Complete: instance Bounded EdgeType
- Data.GraphViz.Attributes.Complete: instance Bounded GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance Bounded Justification
- Data.GraphViz.Attributes.Complete: instance Bounded LabelScheme
- Data.GraphViz.Attributes.Complete: instance Bounded ModeType
- Data.GraphViz.Attributes.Complete: instance Bounded Model
- Data.GraphViz.Attributes.Complete: instance Bounded Order
- Data.GraphViz.Attributes.Complete: instance Bounded OutputMode
- Data.GraphViz.Attributes.Complete: instance Bounded PageDir
- Data.GraphViz.Attributes.Complete: instance Bounded QuadType
- Data.GraphViz.Attributes.Complete: instance Bounded RankDir
- Data.GraphViz.Attributes.Complete: instance Bounded RankType
- Data.GraphViz.Attributes.Complete: instance Bounded STStyle
- Data.GraphViz.Attributes.Complete: instance Bounded SVGFontNames
- Data.GraphViz.Attributes.Complete: instance Bounded ScaleType
- Data.GraphViz.Attributes.Complete: instance Bounded Shape
- Data.GraphViz.Attributes.Complete: instance Bounded SmoothType
- Data.GraphViz.Attributes.Complete: instance Bounded VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance Enum ArrowFill
- Data.GraphViz.Attributes.Complete: instance Enum ArrowShape
- Data.GraphViz.Attributes.Complete: instance Enum ArrowSide
- Data.GraphViz.Attributes.Complete: instance Enum ClusterMode
- Data.GraphViz.Attributes.Complete: instance Enum DEConstraints
- Data.GraphViz.Attributes.Complete: instance Enum DirType
- Data.GraphViz.Attributes.Complete: instance Enum EdgeType
- Data.GraphViz.Attributes.Complete: instance Enum GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance Enum Justification
- Data.GraphViz.Attributes.Complete: instance Enum LabelScheme
- Data.GraphViz.Attributes.Complete: instance Enum ModeType
- Data.GraphViz.Attributes.Complete: instance Enum Model
- Data.GraphViz.Attributes.Complete: instance Enum Order
- Data.GraphViz.Attributes.Complete: instance Enum OutputMode
- Data.GraphViz.Attributes.Complete: instance Enum PageDir
- Data.GraphViz.Attributes.Complete: instance Enum QuadType
- Data.GraphViz.Attributes.Complete: instance Enum RankDir
- Data.GraphViz.Attributes.Complete: instance Enum RankType
- Data.GraphViz.Attributes.Complete: instance Enum STStyle
- Data.GraphViz.Attributes.Complete: instance Enum SVGFontNames
- Data.GraphViz.Attributes.Complete: instance Enum ScaleType
- Data.GraphViz.Attributes.Complete: instance Enum Shape
- Data.GraphViz.Attributes.Complete: instance Enum SmoothType
- Data.GraphViz.Attributes.Complete: instance Enum VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance Eq ArrowFill
- Data.GraphViz.Attributes.Complete: instance Eq ArrowModifier
- Data.GraphViz.Attributes.Complete: instance Eq ArrowShape
- Data.GraphViz.Attributes.Complete: instance Eq ArrowSide
- Data.GraphViz.Attributes.Complete: instance Eq ArrowType
- Data.GraphViz.Attributes.Complete: instance Eq AspectType
- Data.GraphViz.Attributes.Complete: instance Eq ClusterMode
- Data.GraphViz.Attributes.Complete: instance Eq DEConstraints
- Data.GraphViz.Attributes.Complete: instance Eq DPoint
- Data.GraphViz.Attributes.Complete: instance Eq DirType
- Data.GraphViz.Attributes.Complete: instance Eq EdgeType
- Data.GraphViz.Attributes.Complete: instance Eq FocusType
- Data.GraphViz.Attributes.Complete: instance Eq GraphSize
- Data.GraphViz.Attributes.Complete: instance Eq GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance Eq Justification
- Data.GraphViz.Attributes.Complete: instance Eq Label
- Data.GraphViz.Attributes.Complete: instance Eq LabelScheme
- Data.GraphViz.Attributes.Complete: instance Eq LayerID
- Data.GraphViz.Attributes.Complete: instance Eq LayerList
- Data.GraphViz.Attributes.Complete: instance Eq LayerListSep
- Data.GraphViz.Attributes.Complete: instance Eq LayerRangeElem
- Data.GraphViz.Attributes.Complete: instance Eq LayerSep
- Data.GraphViz.Attributes.Complete: instance Eq ModeType
- Data.GraphViz.Attributes.Complete: instance Eq Model
- Data.GraphViz.Attributes.Complete: instance Eq Order
- Data.GraphViz.Attributes.Complete: instance Eq OutputMode
- Data.GraphViz.Attributes.Complete: instance Eq Overlap
- Data.GraphViz.Attributes.Complete: instance Eq Pack
- Data.GraphViz.Attributes.Complete: instance Eq PackMode
- Data.GraphViz.Attributes.Complete: instance Eq PageDir
- Data.GraphViz.Attributes.Complete: instance Eq Paths
- Data.GraphViz.Attributes.Complete: instance Eq Point
- Data.GraphViz.Attributes.Complete: instance Eq Pos
- Data.GraphViz.Attributes.Complete: instance Eq QuadType
- Data.GraphViz.Attributes.Complete: instance Eq RankDir
- Data.GraphViz.Attributes.Complete: instance Eq RankType
- Data.GraphViz.Attributes.Complete: instance Eq Ratios
- Data.GraphViz.Attributes.Complete: instance Eq RecordField
- Data.GraphViz.Attributes.Complete: instance Eq Rect
- Data.GraphViz.Attributes.Complete: instance Eq Root
- Data.GraphViz.Attributes.Complete: instance Eq STStyle
- Data.GraphViz.Attributes.Complete: instance Eq SVGFontNames
- Data.GraphViz.Attributes.Complete: instance Eq ScaleType
- Data.GraphViz.Attributes.Complete: instance Eq Shape
- Data.GraphViz.Attributes.Complete: instance Eq SmoothType
- Data.GraphViz.Attributes.Complete: instance Eq Spline
- Data.GraphViz.Attributes.Complete: instance Eq StartType
- Data.GraphViz.Attributes.Complete: instance Eq StyleItem
- Data.GraphViz.Attributes.Complete: instance Eq StyleName
- Data.GraphViz.Attributes.Complete: instance Eq VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance Eq ViewPort
- Data.GraphViz.Attributes.Complete: instance Ord ArrowFill
- Data.GraphViz.Attributes.Complete: instance Ord ArrowModifier
- Data.GraphViz.Attributes.Complete: instance Ord ArrowShape
- Data.GraphViz.Attributes.Complete: instance Ord ArrowSide
- Data.GraphViz.Attributes.Complete: instance Ord ArrowType
- Data.GraphViz.Attributes.Complete: instance Ord AspectType
- Data.GraphViz.Attributes.Complete: instance Ord ClusterMode
- Data.GraphViz.Attributes.Complete: instance Ord DEConstraints
- Data.GraphViz.Attributes.Complete: instance Ord DPoint
- Data.GraphViz.Attributes.Complete: instance Ord DirType
- Data.GraphViz.Attributes.Complete: instance Ord EdgeType
- Data.GraphViz.Attributes.Complete: instance Ord FocusType
- Data.GraphViz.Attributes.Complete: instance Ord GraphSize
- Data.GraphViz.Attributes.Complete: instance Ord GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance Ord Justification
- Data.GraphViz.Attributes.Complete: instance Ord Label
- Data.GraphViz.Attributes.Complete: instance Ord LabelScheme
- Data.GraphViz.Attributes.Complete: instance Ord LayerID
- Data.GraphViz.Attributes.Complete: instance Ord LayerList
- Data.GraphViz.Attributes.Complete: instance Ord LayerListSep
- Data.GraphViz.Attributes.Complete: instance Ord LayerRangeElem
- Data.GraphViz.Attributes.Complete: instance Ord LayerSep
- Data.GraphViz.Attributes.Complete: instance Ord ModeType
- Data.GraphViz.Attributes.Complete: instance Ord Model
- Data.GraphViz.Attributes.Complete: instance Ord Order
- Data.GraphViz.Attributes.Complete: instance Ord OutputMode
- Data.GraphViz.Attributes.Complete: instance Ord Overlap
- Data.GraphViz.Attributes.Complete: instance Ord Pack
- Data.GraphViz.Attributes.Complete: instance Ord PackMode
- Data.GraphViz.Attributes.Complete: instance Ord PageDir
- Data.GraphViz.Attributes.Complete: instance Ord Paths
- Data.GraphViz.Attributes.Complete: instance Ord Point
- Data.GraphViz.Attributes.Complete: instance Ord Pos
- Data.GraphViz.Attributes.Complete: instance Ord QuadType
- Data.GraphViz.Attributes.Complete: instance Ord RankDir
- Data.GraphViz.Attributes.Complete: instance Ord RankType
- Data.GraphViz.Attributes.Complete: instance Ord Ratios
- Data.GraphViz.Attributes.Complete: instance Ord RecordField
- Data.GraphViz.Attributes.Complete: instance Ord Rect
- Data.GraphViz.Attributes.Complete: instance Ord Root
- Data.GraphViz.Attributes.Complete: instance Ord STStyle
- Data.GraphViz.Attributes.Complete: instance Ord SVGFontNames
- Data.GraphViz.Attributes.Complete: instance Ord ScaleType
- Data.GraphViz.Attributes.Complete: instance Ord Shape
- Data.GraphViz.Attributes.Complete: instance Ord SmoothType
- Data.GraphViz.Attributes.Complete: instance Ord Spline
- Data.GraphViz.Attributes.Complete: instance Ord StartType
- Data.GraphViz.Attributes.Complete: instance Ord StyleItem
- Data.GraphViz.Attributes.Complete: instance Ord StyleName
- Data.GraphViz.Attributes.Complete: instance Ord VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance Ord ViewPort
- Data.GraphViz.Attributes.Complete: instance ParseDot ArrowFill
- Data.GraphViz.Attributes.Complete: instance ParseDot ArrowModifier
- Data.GraphViz.Attributes.Complete: instance ParseDot ArrowShape
- Data.GraphViz.Attributes.Complete: instance ParseDot ArrowSide
- Data.GraphViz.Attributes.Complete: instance ParseDot ArrowType
- Data.GraphViz.Attributes.Complete: instance ParseDot AspectType
- Data.GraphViz.Attributes.Complete: instance ParseDot ClusterMode
- Data.GraphViz.Attributes.Complete: instance ParseDot DEConstraints
- Data.GraphViz.Attributes.Complete: instance ParseDot DPoint
- Data.GraphViz.Attributes.Complete: instance ParseDot DirType
- Data.GraphViz.Attributes.Complete: instance ParseDot EdgeType
- Data.GraphViz.Attributes.Complete: instance ParseDot FocusType
- Data.GraphViz.Attributes.Complete: instance ParseDot GraphSize
- Data.GraphViz.Attributes.Complete: instance ParseDot GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance ParseDot Justification
- Data.GraphViz.Attributes.Complete: instance ParseDot Label
- Data.GraphViz.Attributes.Complete: instance ParseDot LabelScheme
- Data.GraphViz.Attributes.Complete: instance ParseDot LayerID
- Data.GraphViz.Attributes.Complete: instance ParseDot LayerList
- Data.GraphViz.Attributes.Complete: instance ParseDot LayerListSep
- Data.GraphViz.Attributes.Complete: instance ParseDot LayerRangeElem
- Data.GraphViz.Attributes.Complete: instance ParseDot LayerSep
- Data.GraphViz.Attributes.Complete: instance ParseDot ModeType
- Data.GraphViz.Attributes.Complete: instance ParseDot Model
- Data.GraphViz.Attributes.Complete: instance ParseDot Order
- Data.GraphViz.Attributes.Complete: instance ParseDot OutputMode
- Data.GraphViz.Attributes.Complete: instance ParseDot Overlap
- Data.GraphViz.Attributes.Complete: instance ParseDot Pack
- Data.GraphViz.Attributes.Complete: instance ParseDot PackMode
- Data.GraphViz.Attributes.Complete: instance ParseDot PageDir
- Data.GraphViz.Attributes.Complete: instance ParseDot Paths
- Data.GraphViz.Attributes.Complete: instance ParseDot Point
- Data.GraphViz.Attributes.Complete: instance ParseDot Pos
- Data.GraphViz.Attributes.Complete: instance ParseDot QuadType
- Data.GraphViz.Attributes.Complete: instance ParseDot RankDir
- Data.GraphViz.Attributes.Complete: instance ParseDot RankType
- Data.GraphViz.Attributes.Complete: instance ParseDot Ratios
- Data.GraphViz.Attributes.Complete: instance ParseDot RecordField
- Data.GraphViz.Attributes.Complete: instance ParseDot Rect
- Data.GraphViz.Attributes.Complete: instance ParseDot Root
- Data.GraphViz.Attributes.Complete: instance ParseDot STStyle
- Data.GraphViz.Attributes.Complete: instance ParseDot SVGFontNames
- Data.GraphViz.Attributes.Complete: instance ParseDot ScaleType
- Data.GraphViz.Attributes.Complete: instance ParseDot Shape
- Data.GraphViz.Attributes.Complete: instance ParseDot SmoothType
- Data.GraphViz.Attributes.Complete: instance ParseDot Spline
- Data.GraphViz.Attributes.Complete: instance ParseDot StartType
- Data.GraphViz.Attributes.Complete: instance ParseDot StyleItem
- Data.GraphViz.Attributes.Complete: instance ParseDot StyleName
- Data.GraphViz.Attributes.Complete: instance ParseDot VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance ParseDot ViewPort
- Data.GraphViz.Attributes.Complete: instance PrintDot ArrowFill
- Data.GraphViz.Attributes.Complete: instance PrintDot ArrowModifier
- Data.GraphViz.Attributes.Complete: instance PrintDot ArrowShape
- Data.GraphViz.Attributes.Complete: instance PrintDot ArrowSide
- Data.GraphViz.Attributes.Complete: instance PrintDot ArrowType
- Data.GraphViz.Attributes.Complete: instance PrintDot AspectType
- Data.GraphViz.Attributes.Complete: instance PrintDot ClusterMode
- Data.GraphViz.Attributes.Complete: instance PrintDot DEConstraints
- Data.GraphViz.Attributes.Complete: instance PrintDot DPoint
- Data.GraphViz.Attributes.Complete: instance PrintDot DirType
- Data.GraphViz.Attributes.Complete: instance PrintDot EdgeType
- Data.GraphViz.Attributes.Complete: instance PrintDot FocusType
- Data.GraphViz.Attributes.Complete: instance PrintDot GraphSize
- Data.GraphViz.Attributes.Complete: instance PrintDot GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance PrintDot Justification
- Data.GraphViz.Attributes.Complete: instance PrintDot Label
- Data.GraphViz.Attributes.Complete: instance PrintDot LabelScheme
- Data.GraphViz.Attributes.Complete: instance PrintDot LayerID
- Data.GraphViz.Attributes.Complete: instance PrintDot LayerList
- Data.GraphViz.Attributes.Complete: instance PrintDot LayerListSep
- Data.GraphViz.Attributes.Complete: instance PrintDot LayerRangeElem
- Data.GraphViz.Attributes.Complete: instance PrintDot LayerSep
- Data.GraphViz.Attributes.Complete: instance PrintDot ModeType
- Data.GraphViz.Attributes.Complete: instance PrintDot Model
- Data.GraphViz.Attributes.Complete: instance PrintDot Order
- Data.GraphViz.Attributes.Complete: instance PrintDot OutputMode
- Data.GraphViz.Attributes.Complete: instance PrintDot Overlap
- Data.GraphViz.Attributes.Complete: instance PrintDot Pack
- Data.GraphViz.Attributes.Complete: instance PrintDot PackMode
- Data.GraphViz.Attributes.Complete: instance PrintDot PageDir
- Data.GraphViz.Attributes.Complete: instance PrintDot Paths
- Data.GraphViz.Attributes.Complete: instance PrintDot Point
- Data.GraphViz.Attributes.Complete: instance PrintDot Pos
- Data.GraphViz.Attributes.Complete: instance PrintDot QuadType
- Data.GraphViz.Attributes.Complete: instance PrintDot RankDir
- Data.GraphViz.Attributes.Complete: instance PrintDot RankType
- Data.GraphViz.Attributes.Complete: instance PrintDot Ratios
- Data.GraphViz.Attributes.Complete: instance PrintDot RecordField
- Data.GraphViz.Attributes.Complete: instance PrintDot Rect
- Data.GraphViz.Attributes.Complete: instance PrintDot Root
- Data.GraphViz.Attributes.Complete: instance PrintDot STStyle
- Data.GraphViz.Attributes.Complete: instance PrintDot SVGFontNames
- Data.GraphViz.Attributes.Complete: instance PrintDot ScaleType
- Data.GraphViz.Attributes.Complete: instance PrintDot Shape
- Data.GraphViz.Attributes.Complete: instance PrintDot SmoothType
- Data.GraphViz.Attributes.Complete: instance PrintDot Spline
- Data.GraphViz.Attributes.Complete: instance PrintDot StartType
- Data.GraphViz.Attributes.Complete: instance PrintDot StyleItem
- Data.GraphViz.Attributes.Complete: instance PrintDot StyleName
- Data.GraphViz.Attributes.Complete: instance PrintDot VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance PrintDot ViewPort
- Data.GraphViz.Attributes.Complete: instance Read ArrowFill
- Data.GraphViz.Attributes.Complete: instance Read ArrowModifier
- Data.GraphViz.Attributes.Complete: instance Read ArrowShape
- Data.GraphViz.Attributes.Complete: instance Read ArrowSide
- Data.GraphViz.Attributes.Complete: instance Read ArrowType
- Data.GraphViz.Attributes.Complete: instance Read AspectType
- Data.GraphViz.Attributes.Complete: instance Read ClusterMode
- Data.GraphViz.Attributes.Complete: instance Read DEConstraints
- Data.GraphViz.Attributes.Complete: instance Read DPoint
- Data.GraphViz.Attributes.Complete: instance Read DirType
- Data.GraphViz.Attributes.Complete: instance Read EdgeType
- Data.GraphViz.Attributes.Complete: instance Read FocusType
- Data.GraphViz.Attributes.Complete: instance Read GraphSize
- Data.GraphViz.Attributes.Complete: instance Read GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance Read Justification
- Data.GraphViz.Attributes.Complete: instance Read Label
- Data.GraphViz.Attributes.Complete: instance Read LabelScheme
- Data.GraphViz.Attributes.Complete: instance Read LayerID
- Data.GraphViz.Attributes.Complete: instance Read LayerList
- Data.GraphViz.Attributes.Complete: instance Read LayerListSep
- Data.GraphViz.Attributes.Complete: instance Read LayerRangeElem
- Data.GraphViz.Attributes.Complete: instance Read LayerSep
- Data.GraphViz.Attributes.Complete: instance Read ModeType
- Data.GraphViz.Attributes.Complete: instance Read Model
- Data.GraphViz.Attributes.Complete: instance Read Order
- Data.GraphViz.Attributes.Complete: instance Read OutputMode
- Data.GraphViz.Attributes.Complete: instance Read Overlap
- Data.GraphViz.Attributes.Complete: instance Read Pack
- Data.GraphViz.Attributes.Complete: instance Read PackMode
- Data.GraphViz.Attributes.Complete: instance Read PageDir
- Data.GraphViz.Attributes.Complete: instance Read Paths
- Data.GraphViz.Attributes.Complete: instance Read Point
- Data.GraphViz.Attributes.Complete: instance Read Pos
- Data.GraphViz.Attributes.Complete: instance Read QuadType
- Data.GraphViz.Attributes.Complete: instance Read RankDir
- Data.GraphViz.Attributes.Complete: instance Read RankType
- Data.GraphViz.Attributes.Complete: instance Read Ratios
- Data.GraphViz.Attributes.Complete: instance Read RecordField
- Data.GraphViz.Attributes.Complete: instance Read Rect
- Data.GraphViz.Attributes.Complete: instance Read Root
- Data.GraphViz.Attributes.Complete: instance Read STStyle
- Data.GraphViz.Attributes.Complete: instance Read SVGFontNames
- Data.GraphViz.Attributes.Complete: instance Read ScaleType
- Data.GraphViz.Attributes.Complete: instance Read Shape
- Data.GraphViz.Attributes.Complete: instance Read SmoothType
- Data.GraphViz.Attributes.Complete: instance Read Spline
- Data.GraphViz.Attributes.Complete: instance Read StartType
- Data.GraphViz.Attributes.Complete: instance Read StyleItem
- Data.GraphViz.Attributes.Complete: instance Read StyleName
- Data.GraphViz.Attributes.Complete: instance Read VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance Read ViewPort
- Data.GraphViz.Attributes.Complete: instance Show ArrowFill
- Data.GraphViz.Attributes.Complete: instance Show ArrowModifier
- Data.GraphViz.Attributes.Complete: instance Show ArrowShape
- Data.GraphViz.Attributes.Complete: instance Show ArrowSide
- Data.GraphViz.Attributes.Complete: instance Show ArrowType
- Data.GraphViz.Attributes.Complete: instance Show AspectType
- Data.GraphViz.Attributes.Complete: instance Show ClusterMode
- Data.GraphViz.Attributes.Complete: instance Show DEConstraints
- Data.GraphViz.Attributes.Complete: instance Show DPoint
- Data.GraphViz.Attributes.Complete: instance Show DirType
- Data.GraphViz.Attributes.Complete: instance Show EdgeType
- Data.GraphViz.Attributes.Complete: instance Show FocusType
- Data.GraphViz.Attributes.Complete: instance Show GraphSize
- Data.GraphViz.Attributes.Complete: instance Show GraphvizCommand
- Data.GraphViz.Attributes.Complete: instance Show Justification
- Data.GraphViz.Attributes.Complete: instance Show Label
- Data.GraphViz.Attributes.Complete: instance Show LabelScheme
- Data.GraphViz.Attributes.Complete: instance Show LayerID
- Data.GraphViz.Attributes.Complete: instance Show LayerList
- Data.GraphViz.Attributes.Complete: instance Show LayerListSep
- Data.GraphViz.Attributes.Complete: instance Show LayerRangeElem
- Data.GraphViz.Attributes.Complete: instance Show LayerSep
- Data.GraphViz.Attributes.Complete: instance Show ModeType
- Data.GraphViz.Attributes.Complete: instance Show Model
- Data.GraphViz.Attributes.Complete: instance Show Order
- Data.GraphViz.Attributes.Complete: instance Show OutputMode
- Data.GraphViz.Attributes.Complete: instance Show Overlap
- Data.GraphViz.Attributes.Complete: instance Show Pack
- Data.GraphViz.Attributes.Complete: instance Show PackMode
- Data.GraphViz.Attributes.Complete: instance Show PageDir
- Data.GraphViz.Attributes.Complete: instance Show Paths
- Data.GraphViz.Attributes.Complete: instance Show Point
- Data.GraphViz.Attributes.Complete: instance Show Pos
- Data.GraphViz.Attributes.Complete: instance Show QuadType
- Data.GraphViz.Attributes.Complete: instance Show RankDir
- Data.GraphViz.Attributes.Complete: instance Show RankType
- Data.GraphViz.Attributes.Complete: instance Show Ratios
- Data.GraphViz.Attributes.Complete: instance Show RecordField
- Data.GraphViz.Attributes.Complete: instance Show Rect
- Data.GraphViz.Attributes.Complete: instance Show Root
- Data.GraphViz.Attributes.Complete: instance Show STStyle
- Data.GraphViz.Attributes.Complete: instance Show SVGFontNames
- Data.GraphViz.Attributes.Complete: instance Show ScaleType
- Data.GraphViz.Attributes.Complete: instance Show Shape
- Data.GraphViz.Attributes.Complete: instance Show SmoothType
- Data.GraphViz.Attributes.Complete: instance Show Spline
- Data.GraphViz.Attributes.Complete: instance Show StartType
- Data.GraphViz.Attributes.Complete: instance Show StyleItem
- Data.GraphViz.Attributes.Complete: instance Show StyleName
- Data.GraphViz.Attributes.Complete: instance Show VerticalPlacement
- Data.GraphViz.Attributes.Complete: instance Show ViewPort
- Data.GraphViz.Commands: instance Bounded GraphvizOutput
- Data.GraphViz.Commands: instance Enum GraphvizOutput
- Data.GraphViz.Parsing: bracket :: Parse bra -> Parse ket -> Parse a -> Parse a
- Data.GraphViz.Types.Canonical: Dbl :: Double -> GraphID
- Data.GraphViz.Types.Canonical: Int :: Int -> GraphID
- Data.GraphViz.Types.Generalised: Dbl :: Double -> GraphID
- Data.GraphViz.Types.Generalised: Int :: Int -> GraphID
- Data.GraphViz.Types.Graph: Dbl :: Double -> GraphID
- Data.GraphViz.Types.Graph: Int :: Int -> GraphID
- Data.GraphViz.Types.Monadic: Dbl :: Double -> GraphID
- Data.GraphViz.Types.Monadic: Int :: Int -> GraphID
+ Data.GraphViz.Attributes: Square :: Shape
+ Data.GraphViz.Attributes: Star :: Shape
+ Data.GraphViz.Attributes: Underline :: Shape
+ Data.GraphViz.Attributes.Complete: Background :: Text -> Attribute
+ Data.GraphViz.Attributes.Complete: Dbl :: Double -> Number
+ Data.GraphViz.Attributes.Complete: GrowAsNeeded :: NodeSize
+ Data.GraphViz.Attributes.Complete: InputScale :: Double -> Attribute
+ Data.GraphViz.Attributes.Complete: Int :: Int -> Number
+ Data.GraphViz.Attributes.Complete: IsNormalized :: Normalized
+ Data.GraphViz.Attributes.Complete: MaxEnt :: ModeType
+ Data.GraphViz.Attributes.Complete: NormalizedAngle :: Double -> Normalized
+ Data.GraphViz.Attributes.Complete: NotNormalized :: Normalized
+ Data.GraphViz.Attributes.Complete: OverlapShrink :: Bool -> Attribute
+ Data.GraphViz.Attributes.Complete: SetNodeSize :: NodeSize
+ Data.GraphViz.Attributes.Complete: SetShapeSize :: NodeSize
+ Data.GraphViz.Attributes.Complete: SpringMode :: ModeType
+ Data.GraphViz.Attributes.Complete: Square :: Shape
+ Data.GraphViz.Attributes.Complete: Star :: Shape
+ Data.GraphViz.Attributes.Complete: Underline :: Shape
+ Data.GraphViz.Attributes.Complete: XDotVersion :: Version -> Attribute
+ Data.GraphViz.Attributes.Complete: data NodeSize
+ Data.GraphViz.Attributes.Complete: data Normalized
+ Data.GraphViz.Attributes.Complete: data Number
+ Data.GraphViz.Parsing: instance ParseDot Version
+ Data.GraphViz.Parsing: parseLiberally :: GraphvizState -> GraphvizState
+ Data.GraphViz.Parsing: parseSignedFloat :: Bool -> Parse Double
+ Data.GraphViz.Parsing: runParserWith :: (GraphvizState -> GraphvizState) -> Parse a -> Text -> (Either String a, Text)
+ Data.GraphViz.Printing: instance PrintDot Version
+ Data.GraphViz.Types: Num :: Number -> GraphID
+ Data.GraphViz.Types: data Number
+ Data.GraphViz.Types: parseDotGraphLiberally :: ParseDotRepr dg n => Text -> dg n
+ Data.GraphViz.Types.Canonical: Num :: Number -> GraphID
+ Data.GraphViz.Types.Generalised: Num :: Number -> GraphID
+ Data.GraphViz.Types.Generalised: class DotRepr dg n => FromGeneralisedDot dg n
+ Data.GraphViz.Types.Generalised: fromGeneralised :: FromGeneralisedDot dg n => DotGraph n -> dg n
+ Data.GraphViz.Types.Generalised: instance Ord n => FromGeneralisedDot DotGraph n
+ Data.GraphViz.Types.Graph: Num :: Number -> GraphID
+ Data.GraphViz.Types.Graph: instance Ord n => FromGeneralisedDot DotGraph n
+ Data.GraphViz.Types.Monadic: Num :: Number -> GraphID
+ Data.GraphViz.Types.Monadic: instance Applicative (DotM n)
+ Data.GraphViz.Types.Monadic: instance Functor (DotM n)
- Data.GraphViz: dotAttributes :: (Graph gr, PPDotRepr dg Node) => Bool -> gr nl (EdgeID el) -> dg Node -> IO (gr (AttributeNode nl) (AttributeEdge el))
+ Data.GraphViz: dotAttributes :: (Graph gr, PPDotRepr dg Node, FromGeneralisedDot dg Node) => Bool -> gr nl (EdgeID el) -> dg Node -> IO (gr (AttributeNode nl) (AttributeEdge el))
- Data.GraphViz.Attributes: normal :: Arrow
+ Data.GraphViz.Attributes: normal :: ArrowType
- Data.GraphViz.Attributes.Complete: FixedSize :: Bool -> Attribute
+ Data.GraphViz.Attributes.Complete: FixedSize :: NodeSize -> Attribute
- Data.GraphViz.Attributes.Complete: Normalize :: Bool -> Attribute
+ Data.GraphViz.Attributes.Complete: Normalize :: Normalized -> Attribute
- Data.GraphViz.Attributes.Complete: Weight :: Double -> Attribute
+ Data.GraphViz.Attributes.Complete: Weight :: Number -> Attribute
- Data.GraphViz.Commands: XDot :: GraphvizOutput
+ Data.GraphViz.Commands: XDot :: (Maybe Version) -> GraphvizOutput
- Data.GraphViz.Parsing: numString :: Parse Text
+ Data.GraphViz.Parsing: numString :: Bool -> Parse Text
- Data.GraphViz.Parsing: parseStrictFloat :: Parse Double
+ Data.GraphViz.Parsing: parseStrictFloat :: Bool -> Parse Double
- Data.GraphViz.Types: Dbl :: Double -> GraphID
+ Data.GraphViz.Types: Dbl :: Double -> Number
- Data.GraphViz.Types: Int :: Int -> GraphID
+ Data.GraphViz.Types: Int :: Int -> Number
Files
- Changelog.md +89/−0
- Data/GraphViz.hs +29/−26
- Data/GraphViz/Algorithms.hs +17/−16
- Data/GraphViz/Attributes.hs +12/−8
- Data/GraphViz/Attributes/Arrows.hs +155/−0
- Data/GraphViz/Attributes/Colors.hs +28/−28
- Data/GraphViz/Attributes/Complete.hs +1551/−3189
- Data/GraphViz/Attributes/HTML.hs +18/−16
- Data/GraphViz/Attributes/Internal.hs +6/−5
- Data/GraphViz/Attributes/Values.hs +1631/−0
- Data/GraphViz/Commands.hs +21/−18
- Data/GraphViz/Commands/Available.hs +63/−0
- Data/GraphViz/Commands/IO.hs +27/−21
- Data/GraphViz/Internal/State.hs +138/−0
- Data/GraphViz/Internal/Util.hs +165/−0
- Data/GraphViz/Parsing.hs +104/−79
- Data/GraphViz/Printing.hs +28/−23
- Data/GraphViz/State.hs +0/−132
- Data/GraphViz/Types.hs +69/−43
- Data/GraphViz/Types/Canonical.hs +4/−4
- Data/GraphViz/Types/Common.hs +0/−528
- Data/GraphViz/Types/Generalised.hs +35/−16
- Data/GraphViz/Types/Graph.hs +28/−22
- Data/GraphViz/Types/Internal/Common.hs +547/−0
- Data/GraphViz/Types/Monadic.hs +14/−6
- Data/GraphViz/Types/State.hs +16/−16
- Data/GraphViz/Util.hs +0/−165
- FAQ.md +34/−30
- TODO.md +2/−0
- graphviz.cabal +48/−25
- tests/Data/GraphViz/Testing/Instances/Attributes.hs +67/−28
- tests/Data/GraphViz/Testing/Instances/Canonical.hs +2/−2
- tests/Data/GraphViz/Testing/Instances/Common.hs +7/−9
- tests/Data/GraphViz/Testing/Instances/FGL.hs +5/−5
- tests/Data/GraphViz/Testing/Instances/Generalised.hs +4/−4
- tests/Data/GraphViz/Testing/Instances/Helpers.hs +11/−11
- tests/Data/GraphViz/Testing/Properties.hs +28/−21
- utils/AttributeGenerator.hs +228/−219
- utils/TestParsing.hs +14/−14
Changelog.md view
@@ -7,6 +7,95 @@ The following is information about what major changes have gone into each release. +Changes in 2999.17.0.0+----------------------++* Add support for Graphviz 2.32.0, 2.32.1, 2.34.0, 2.36.0 and 2.38.0:++ - **WARNING**: at least as of Graphviz-2.32.0, `dot -Tcanon` no+ longer produces Dot code that is in the format expected by the+ Canonical Dot representation in this library. As such, unless+ you're very sure of your sources you should _always_ use the+ Generalised representation for parsing (see also the new+ `FromGeneralisedDot` class mentioned below).++ - New attributes:++ + `XDotVersion` (as of 2.34.0)++ + `InputScale` (as of 2.36.0)++ + `OverlapShrink` (as of 2.36.0)++ - Changed attributes:++ + `Aspect` no longer available (as of 2.36.0)++ + New `ModeType` values for use with `sfdp`: `SpringMode` and+ `MaxEnt`.++ + `Weight` now takes a value of type `Number`, that explicitly+ distinguishes between `Doubles` and `Ints`.++ + `FixedSize` and `Normalize` now have their own types.++ + New `Shape`s: `Star` and `Underline` (as well as `Square`+ which seems to have been omitted from previous versions).++ - Other relevant changes:++ + `XDot` now takes an optional version. Note that this+ doesn't have any effect on how _graphviz_ works.++ + The default extension for Dot-graphs is now `.gv` rather+ than `.dot` to reflect Graphviz's changed conventions.++* Other changes to the API:++ - Add the `FromGeneralisedDot` class, which provides a+ semi-inverse to `fromCanonical` in `DotRepr`.++ - `GraphID` now uses `Number` rather than separate `Int` and+ `Double` constructors; this only matters if you manually+ constructed or de-constructed `GraphID` values (`ToGraphID`+ still works).++ - Add the ability to parse a Dot graph "liberally": that is, if an+ `Attribute` doesn't match the specification, then let it fall+ back to an `UnknownAttribute`. This is still experimental, and+ requires more manual usage than the in-built commands (e.g. it+ isn't supported in the default round-tripping).++ - Now using the definition of `bracket` from `polyparse >= 1.9`.++ - Monadic representation now has `Functor` and `Applicative`+ instances to satisfy the up-coming changes in GHC 7.10.++* Compilation time has been reduced in two ways:++ - The `Data.GraphViz.Attributes.Complete` module has been split up+ (but still exports the same API, so no need to import more+ modules). Whilst I haven't measured it, this should also reduce+ memory requirements for compilation.++ - The testsuite now uses the library explicitly, and thus no+ longer needs to re-compile half the library.++* Bug-fixes:++ - Double values are now longer parseable without double quotes if+ they have an exponential term (to better match the definition).++ - It is no longer assumed when round-tripping that `dot -Tdot`+ generates canonicalised Dot graphs.++* The `TestParsing` script is now directly buildable by Cabal using+ the `test-parsing` flag (the resulting executable is called+ `graphviz-testparsing`). This is not made an actual test-suite as+ not all files found will be actual Dot graphs, and it's known that+ it fails on some. Instead it's meant to be used as an indication of+ how well this library parses "real-world" Dot code.+ Changes in 2999.16.0.0 ----------------------
Data/GraphViz.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses, OverloadedStrings #-} {- | Module : Data.GraphViz@@ -9,8 +9,8 @@ This is the top-level module for the graphviz library. It provides functions to convert 'Data.Graph.Inductive.Graph.Graph's into the- /Dot/ language used by the /Graphviz/ suite of programs (as well as- a limited ability to perform the reverse operation).+ /Dot/ language used by the /Graphviz/ suite of programs (as well as a+ limited ability to perform the reverse operation). If you wish to construct a Haskell representation of a Dot graph yourself rather than using the conversion functions here, please@@ -19,8 +19,8 @@ Information about Graphviz and the Dot language can be found at: <http://graphviz.org/>- -}+ module Data.GraphViz ( -- * Conversion from graphs to /Dot/ format. -- ** Specifying parameters.@@ -63,28 +63,29 @@ , module Data.GraphViz.Commands ) where -import Data.GraphViz.Types-import Data.GraphViz.Types.Canonical( DotGraph(..), DotStatements(..)- , DotSubGraph(..)) import Data.GraphViz.Algorithms.Clustering-import Data.GraphViz.Util(uniq, uniqBy) import Data.GraphViz.Attributes-import Data.GraphViz.Attributes.Complete(CustomAttribute, AttributeName- , customAttribute, findSpecifiedCustom- , customValue)+import Data.GraphViz.Attributes.Complete (AttributeName, CustomAttribute,+ customAttribute, customValue,+ findSpecifiedCustom) import Data.GraphViz.Commands-import Data.GraphViz.Commands.IO(hGetDot)+import Data.GraphViz.Commands.IO (hGetDot)+import Data.GraphViz.Internal.Util (uniq, uniqBy)+import Data.GraphViz.Types+import Data.GraphViz.Types.Canonical (DotGraph (..), DotStatements (..),+ DotSubGraph (..))+import Data.GraphViz.Types.Generalised (FromGeneralisedDot (..)) -import Data.Functor((<$>))-import Data.Graph.Inductive.Graph-import qualified Data.Set as Set-import Control.Arrow((&&&), first)-import Data.Maybe(mapMaybe, fromJust)-import qualified Data.Map as Map-import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)-import System.IO.Unsafe(unsafePerformIO)-import Control.Concurrent(forkIO)+import Control.Arrow (first, (&&&))+import Control.Concurrent (forkIO)+import Data.Functor ((<$>))+import Data.Graph.Inductive.Graph+import qualified Data.Map as Map+import Data.Maybe (fromJust, mapMaybe)+import qualified Data.Set as Set+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import System.IO.Unsafe (unsafePerformIO) -- ----------------------------------------------------------------------------- @@ -143,7 +144,7 @@ > where > params = blankParams { globalAttributes = [] > , clusterBy = clustBy- > , clusterID = Int+ > , clusterID = Num . Int > , fmtCluster = clFmt > , fmtNode = const [] > , fmtEdge = const []@@ -198,6 +199,7 @@ , fmtEdge :: ((n,n,el) -> Attributes) } + -- | An alias for 'NodeCluster' when dealing with FGL graphs. type LNodeCluster cl l = NodeCluster cl (Node,l) @@ -217,7 +219,7 @@ , globalAttributes = [] , clusterBy = N , isDotCluster = const True- , clusterID = const (Int 0)+ , clusterID = const (Num $ Int 0) , fmtCluster = const [] , fmtNode = const [] , fmtEdge = const []@@ -444,12 +446,13 @@ -- | Pass the 'DotRepr' through the relevant command and then augment -- the 'Graph' that it came from.-dotAttributes :: (Graph gr, PPDotRepr dg Node) => Bool -> gr nl (EdgeID el)+dotAttributes :: (Graph gr, PPDotRepr dg Node, FromGeneralisedDot dg Node)+ => Bool -> gr nl (EdgeID el) -> dg Node -> IO (gr (AttributeNode nl) (AttributeEdge el)) dotAttributes isDir gr dot = augmentGraph gr . parseDG <$> graphvizWithHandle command dot DotOutput hGetDot where- parseDG = (`asTypeOf` dot)+ parseDG = (`asTypeOf` dot) . fromGeneralised command = if isDir then dirCommand else undirCommand -- | Use the 'Attributes' in the provided 'DotGraph' to augment the
Data/GraphViz/Algorithms.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE MonadComprehensions #-}+{-# LANGUAGE MonadComprehensions, MultiParamTypeClasses #-} {- | Module : Data.GraphViz.Algorithms@@ -31,25 +31,26 @@ , transitiveReductionOptions ) where -import Data.GraphViz.Attributes.Complete( Attributes, defaultAttributeValue)+import Data.GraphViz.Attributes.Complete (Attributes, defaultAttributeValue) import Data.GraphViz.Attributes.Same+import Data.GraphViz.Internal.Util (bool) import Data.GraphViz.Types import Data.GraphViz.Types.Canonical-import Data.GraphViz.Types.Common-import Data.GraphViz.Util(bool)+import Data.GraphViz.Types.Internal.Common -import Data.Function(on)-import Data.List(groupBy, sortBy, partition, (\\), deleteBy)-import Data.Maybe(listToMaybe, mapMaybe, fromMaybe)-import qualified Data.DList as DList-import qualified Data.Map as Map-import Data.Map(Map)-import qualified Data.Set as Set-import Data.Set(Set)-import qualified Data.Foldable as F-import Control.Arrow(first, second, (***))-import Control.Monad(unless)-import Control.Monad.Trans.State+import Control.Arrow (first, second, (***))+import Control.Monad (unless)+import Control.Monad.Trans.State+import qualified Data.DList as DList+import qualified Data.Foldable as F+import Data.Function (on)+import Data.List (deleteBy, groupBy, partition,+ sortBy, (\\))+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe (fromMaybe, listToMaybe, mapMaybe)+import Data.Set (Set)+import qualified Data.Set as Set -- -----------------------------------------------------------------------------
Data/GraphViz/Attributes.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-} {- | Module : Data.GraphViz.Attributes@@ -93,13 +93,18 @@ , RankType(..) ) where -import Data.GraphViz.Attributes.Complete-import Data.GraphViz.Attributes.Colors.X11-import qualified Data.GraphViz.Attributes.HTML as Html+import Data.GraphViz.Attributes.Arrows+import Data.GraphViz.Attributes.Colors+import Data.GraphViz.Attributes.Colors.X11+import Data.GraphViz.Attributes.Complete (Attribute (..),+ Attributes)+import qualified Data.GraphViz.Attributes.HTML as Html+import Data.GraphViz.Attributes.Internal+import Data.GraphViz.Attributes.Values +import qualified Data.Text as ST+import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)-import qualified Data.Text as ST -- ----------------------------------------------------------------------------- @@ -378,10 +383,9 @@ edgeEnds :: DirType -> Attribute edgeEnds = Dir -box, crow, diamond, dotArrow, inv, noArrow, normal, tee, vee :: Arrow+box, crow, diamond, dotArrow, inv, noArrow, tee, vee :: Arrow oDot, invDot, invODot, oBox, oDiamond :: Arrow -normal = AType [(noMods, Normal)] inv = AType [(noMods, Inv)] dotArrow = AType [(noMods, DotArrow)] invDot = AType [ (noMods, Inv)
+ Data/GraphViz/Attributes/Arrows.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}+{- |+ Module : Data.GraphViz.Attributes.Arrows+ Description : Arrow types+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++++ -}+module Data.GraphViz.Attributes.Arrows where++import Data.GraphViz.Internal.Util (bool)+import Data.GraphViz.Parsing+import Data.GraphViz.Printing++import Data.Maybe (isJust)++-- -----------------------------------------------------------------------------++-- | /Dot/ has a basic grammar of arrow shapes which allows usage of+-- up to 1,544,761 different shapes from 9 different basic+-- 'ArrowShape's. Note that whilst an explicit list is used in the+-- definition of 'ArrowType', there must be at least one tuple and a+-- maximum of 4 (since that is what is required by Dot). For more+-- information, see: <http://graphviz.org/doc/info/arrows.html>+--+-- The 19 basic arrows shown on the overall attributes page have+-- been defined below as a convenience. Parsing of the 5+-- backward-compatible special cases is also supported.+newtype ArrowType = AType [(ArrowModifier, ArrowShape)]+ deriving (Eq, Ord, Show, Read)++-- Used for default+normal :: ArrowType+normal = AType [(noMods, Normal)]++-- Used for backward-compatible parsing+eDiamond, openArr, halfOpen, emptyArr, invEmpty :: ArrowType++eDiamond = AType [(openMod, Diamond)]+openArr = AType [(noMods, Vee)]+halfOpen = AType [(ArrMod FilledArrow LeftSide, Vee)]+emptyArr = AType [(openMod, Normal)]+invEmpty = AType [ (noMods, Inv)+ , (openMod, Normal)]++instance PrintDot ArrowType where+ unqtDot (AType mas) = hcat $ mapM appMod mas+ where+ appMod (m, a) = unqtDot m <> unqtDot a++instance ParseDot ArrowType where+ parseUnqt = specialArrowParse+ `onFail`+ (AType <$> many1 (liftA2 (,) parseUnqt parseUnqt))++specialArrowParse :: Parse ArrowType+specialArrowParse = stringValue [ ("ediamond", eDiamond)+ , ("open", openArr)+ , ("halfopen", halfOpen)+ , ("empty", emptyArr)+ , ("invempty", invEmpty)+ ]++data ArrowShape = Box+ | Crow+ | Diamond+ | DotArrow+ | Inv+ | NoArrow+ | Normal+ | Tee+ | Vee+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot ArrowShape where+ unqtDot Box = text "box"+ unqtDot Crow = text "crow"+ unqtDot Diamond = text "diamond"+ unqtDot DotArrow = text "dot"+ unqtDot Inv = text "inv"+ unqtDot NoArrow = text "none"+ unqtDot Normal = text "normal"+ unqtDot Tee = text "tee"+ unqtDot Vee = text "vee"++instance ParseDot ArrowShape where+ parseUnqt = stringValue [ ("box", Box)+ , ("crow", Crow)+ , ("diamond", Diamond)+ , ("dot", DotArrow)+ , ("inv", Inv)+ , ("none", NoArrow)+ , ("normal", Normal)+ , ("tee", Tee)+ , ("vee", Vee)+ ]++-- | What modifications to apply to an 'ArrowShape'.+data ArrowModifier = ArrMod { arrowFill :: ArrowFill+ , arrowSide :: ArrowSide+ }+ deriving (Eq, Ord, Show, Read)++-- | Apply no modifications to an 'ArrowShape'.+noMods :: ArrowModifier+noMods = ArrMod FilledArrow BothSides++-- | 'OpenArrow' and 'BothSides'+openMod :: ArrowModifier+openMod = ArrMod OpenArrow BothSides++instance PrintDot ArrowModifier where+ unqtDot (ArrMod f s) = unqtDot f <> unqtDot s++instance ParseDot ArrowModifier where+ parseUnqt = liftA2 ArrMod parseUnqt parseUnqt++data ArrowFill = OpenArrow+ | FilledArrow+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot ArrowFill where+ unqtDot OpenArrow = char 'o'+ unqtDot FilledArrow = empty++instance ParseDot ArrowFill where+ parseUnqt = bool FilledArrow OpenArrow . isJust <$> optional (character 'o')++ -- Not used individually+ parse = parseUnqt++-- | Represents which side (when looking towards the node the arrow is+-- pointing to) is drawn.+data ArrowSide = LeftSide+ | RightSide+ | BothSides+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot ArrowSide where+ unqtDot LeftSide = char 'l'+ unqtDot RightSide = char 'r'+ unqtDot BothSides = empty++instance ParseDot ArrowSide where+ parseUnqt = getSideType <$> optional (oneOf $ map character ['l', 'r'])+ where+ getSideType = maybe BothSides+ (bool RightSide LeftSide . (==) 'l')++ -- Not used individually+ parse = parseUnqt
Data/GraphViz/Attributes/Colors.hs view
@@ -36,27 +36,28 @@ , fromAColour ) where +import Data.GraphViz.Attributes.Colors.Brewer (BrewerColor (..))+import Data.GraphViz.Attributes.Colors.SVG (SVGColor, svgColour)+import Data.GraphViz.Attributes.Colors.X11 (X11Color (Transparent),+ x11Colour)+import Data.GraphViz.Attributes.ColorScheme (ColorScheme (..))+import Data.GraphViz.Exception+import Data.GraphViz.Internal.State+import Data.GraphViz.Internal.Util (bool) import Data.GraphViz.Parsing import Data.GraphViz.Printing-import Data.GraphViz.State-import Data.GraphViz.Attributes.ColorScheme(ColorScheme(..))-import Data.GraphViz.Attributes.Colors.X11(X11Color(Transparent), x11Colour)-import Data.GraphViz.Attributes.Colors.SVG(SVGColor, svgColour)-import Data.GraphViz.Attributes.Colors.Brewer(BrewerColor(..))-import Data.GraphViz.Util(bool)-import Data.GraphViz.Exception -import Data.Colour( AlphaColour, opaque, withOpacity- , over, black, alphaChannel, darken)-import Data.Colour.SRGB(Colour, sRGB, sRGB24, toSRGB24)-import Data.Colour.RGBSpace(uncurryRGB)-import Data.Colour.RGBSpace.HSV(hsv)+import Data.Colour (AlphaColour, alphaChannel, black, darken,+ opaque, over, withOpacity)+import Data.Colour.RGBSpace (uncurryRGB)+import Data.Colour.RGBSpace.HSV (hsv)+import Data.Colour.SRGB (Colour, sRGB, sRGB24, toSRGB24) -import Data.Char(isHexDigit)-import Numeric(showHex, readHex)-import Data.Maybe(isJust)-import Data.Word(Word8)+import Data.Char (isHexDigit)+import Data.Maybe (isJust) import qualified Data.Text.Lazy as T+import Data.Word (Word8)+import Numeric (readHex, showHex) -- ----------------------------------------------------------------------------- @@ -130,22 +131,21 @@ fail "Could not parse Color" where parseHexBased- = do character '#'- cs <- many1 parse2Hex+ = character '#' *>+ do cs <- many1 parse2Hex return $ case cs of [r,g,b] -> RGB r g b [r,g,b,a] -> RGBA r g b a _ -> throw . NotDotCode $ "Not a valid hex Color specification: " ++ show cs- parseHSV = HSV <$> parse+ parseHSV = HSV <$> parseUnqt <* parseSep- <*> parse+ <*> parseUnqt <* parseSep- <*> parse- parseSep = oneOf [ string "," *> whitespace- , whitespace1- ]+ <*> parseUnqt+ parseSep = character ',' *> whitespace <|> whitespace1+ parse2Hex = do c1 <- satisfy isHexDigit c2 <- satisfy isHexDigit let [(n, [])] = readHex [c1, c2]@@ -184,7 +184,7 @@ type ColorList = [WeightedColor] -- | A 'Color' tagged with an optional weighting.-data WeightedColor = WC { wColor :: Color+data WeightedColor = WC { wColor :: Color -- | Must be in range @0 <= W <= 1@. , weighting :: Maybe Double }@@ -226,10 +226,10 @@ failBad $ "Error parsing a ColorList with color scheme of " ++ show cs - parseList = ((:[]) . toWC <$> parse)- -- Potentially unquoted un-weighted single color+ parseList = quotedParse parseUnqtList `onFail`- quotedParse parseUnqtList+ ((:[]) . toWC <$> parse)+ -- Potentially unquoted un-weighted single color `onFail` do cs <- getColorScheme failBad $ "Error parsing ColorList with color scheme of "
Data/GraphViz/Attributes/Complete.hs view
@@ -42,3192 +42,1554 @@ expanded upon to give an idea of what they represent rather than using generic terms. - * @PointF@ and 'Point' have been combined. The optional '!' and- third value for Point are also available.-- * 'Rect' uses two 'Point' values to denote the lower-left and- top-right corners.-- * The two 'LabelLoc' attributes have been combined.-- * @SplineType@ has been replaced with @['Spline']@.-- * Only polygon-based 'Shape's are available.-- * Not every 'Attribute' is fully documented/described. However,- all those which have specific allowed values should be covered.-- * Deprecated 'Overlap' algorithms are not defined. Furthermore,- the ability to specify an integer prefix for use with the fdp layout- is /not/ supported.-- * The global @Orientation@ attribute is not defined, as it is- difficult to distinguish from the node-based 'Orientation'- 'Attribute'; also, its behaviour is duplicated by 'Rotate'.-- * The @charset@ attribute is not available, as graphviz only- supports UTF-8 encoding (as it is not currently feasible nor needed to- also support Latin1 encoding).-- * In Graphviz, when a node or edge has a list of attributes, the- colorscheme which is used to identify a color can be set /after/- that color (e.g. @[colorscheme=x11,color=grey,colorscheme=svg]@- uses the svg colorscheme's definition of grey, which is different- from the x11 one. Instead, graphviz parses them in order.-- -}-module Data.GraphViz.Attributes.Complete- ( -- * The actual /Dot/ attributes.- -- $attributes- Attribute(..)- , Attributes- , sameAttribute- , defaultAttributeValue- , rmUnwantedAttributes- -- ** Validity functions on @Attribute@ values.- , usedByGraphs- , usedBySubGraphs- , usedByClusters- , usedByNodes- , usedByEdges- , validUnknown-- -- ** Custom attributes.- , AttributeName- , CustomAttribute- , customAttribute- , isCustom- , isSpecifiedCustom- , customValue- , customName- , findCustoms- , findSpecifiedCustom- , deleteCustomAttributes- , deleteSpecifiedCustom-- -- * Value types for @Attribute@s.- , module Data.GraphViz.Attributes.Colors-- -- ** Labels- , EscString- , Label(..)- , VerticalPlacement(..)- , LabelScheme(..)- , SVGFontNames(..)- -- *** Types representing the Dot grammar for records.- , RecordFields- , RecordField(..)- , Rect(..)- , Justification(..)-- -- ** Nodes- , Shape(..)- , Paths(..)- , ScaleType(..)-- -- ** Edges- , DirType(..)- , EdgeType(..)- -- *** Modifying where edges point- , PortName(..)- , PortPos(..)- , CompassPoint(..)- -- *** Arrows- , ArrowType(..)- , ArrowShape(..)- , ArrowModifier(..)- , ArrowFill(..)- , ArrowSide(..)- -- **** @ArrowModifier@ values- , noMods- , openMod-- -- ** Positioning- , Point(..)- , createPoint- , Pos(..)- , Spline(..)- , DPoint(..)-- -- ** Layout- , GraphvizCommand(..)- , GraphSize(..)- , AspectType(..)- , ClusterMode(..)- , Model(..)- , Overlap(..)- , Root(..)- , Order(..)- , OutputMode(..)- , Pack(..)- , PackMode(..)- , PageDir(..)- , QuadType(..)- , RankType(..)- , RankDir(..)- , StartType(..)- , ViewPort(..)- , FocusType(..)- , Ratios(..)-- -- ** Modes- , ModeType(..)- , DEConstraints(..)-- -- ** Layers- , LayerSep(..)- , LayerListSep(..)- , LayerRange- , LayerRangeElem(..)- , LayerID(..)- , LayerList(..)-- -- ** Stylistic- , SmoothType(..)- , STStyle(..)- , StyleItem(..)- , StyleName(..)- ) where--import Data.GraphViz.Attributes.Colors-import Data.GraphViz.Attributes.Colors.X11(X11Color(Black))-import qualified Data.GraphViz.Attributes.HTML as Html-import Data.GraphViz.Attributes.Internal-import Data.GraphViz.Util-import Data.GraphViz.Parsing-import Data.GraphViz.Printing-import Data.GraphViz.State(getLayerSep, setLayerSep, getLayerListSep, setLayerListSep)-import Data.GraphViz.Exception(GraphvizException(NotCustomAttr), throw)--import Data.List(partition, intercalate)-import Data.Maybe(isJust, isNothing)-import Data.Word(Word16)-import qualified Data.Set as S-import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)-import System.FilePath(searchPathSeparator, splitSearchPath)---- -------------------------------------------------------------------------------{- $attributes-- These attributes have been implemented in a /permissive/ manner:- that is, rather than split them up based on which type of value- they are allowed, they have all been included in the one data type,- with functions to determine if they are indeed valid for what- they're being applied to.-- To interpret the /Valid for/ listings:-- [@G@] Valid for Graphs.-- [@C@] Valid for Clusters.-- [@S@] Valid for Sub-Graphs (and also Clusters).-- [@N@] Valid for Nodes.-- [@E@] Valid for Edges.-- The /Default/ listings are those that the various Graphviz commands- use if that 'Attribute' isn't specified (in cases where this is- /none/, this is equivalent to a 'Nothing' value; that is, no value- is used). The /Parsing Default/ listings represent what value is- used (i.e. corresponds to 'True') when the 'Attribute' name is- listed on its own in /Dot/ source code.-- Please note that the 'UnknownAttribute' 'Attribute' is defined- primarily for backwards-compatibility purposes. It is possible to use- it directly for custom purposes; for more information, please see- 'CustomAttribute'. The 'deleteCustomAttributes' can be used to delete- these values.-- -}---- | Attributes are used to customise the layout and design of Dot--- graphs. Care must be taken to ensure that the attribute you use--- is valid, as not all attributes can be used everywhere.-data Attribute- = Damping Double -- ^ /Valid for/: G; /Default/: @0.99@; /Minimum/: @0.0@; /Notes/: neato only- | K Double -- ^ /Valid for/: GC; /Default/: @0.3@; /Minimum/: @0@; /Notes/: sfdp, fdp only- | URL EscString -- ^ /Valid for/: ENGC; /Default/: none; /Notes/: svg, postscript, map only- | Area Double -- ^ /Valid for/: NC; /Default/: @1.0@; /Minimum/: @>0@; /Notes/: patchwork only, requires Graphviz >= 2.30.0- | ArrowHead ArrowType -- ^ /Valid for/: E; /Default/: @'normal'@- | ArrowSize Double -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0.0@- | ArrowTail ArrowType -- ^ /Valid for/: E; /Default/: @'normal'@- | Aspect AspectType -- ^ /Valid for/: G; /Notes/: dot only- | BoundingBox Rect -- ^ /Valid for/: G; /Notes/: write only- | BgColor ColorList -- ^ /Valid for/: GC; /Default/: @[]@- | Center Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'- | ClusterRank ClusterMode -- ^ /Valid for/: G; /Default/: @'Local'@; /Notes/: dot only- | Color ColorList -- ^ /Valid for/: ENC; /Default/: @['WC' ('X11Color' 'Black') Nothing]@- | ColorScheme ColorScheme -- ^ /Valid for/: ENCG; /Default/: @'X11'@- | Comment Text -- ^ /Valid for/: ENG; /Default/: @\"\"@- | Compound Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: dot only- | Concentrate Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'- | Constraint Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: dot only- | Decorate Bool -- ^ /Valid for/: E; /Default/: @'False'@; /Parsing Default/: 'True'- | DefaultDist Double -- ^ /Valid for/: G; /Default/: @1+(avg. len)*sqrt(abs(V))@ (unable to statically define); /Minimum/: The value of 'Epsilon'.; /Notes/: neato only, only if @'Pack' 'DontPack'@- | Dim Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: maximum of @10@; sfdp, fdp, neato only- | Dimen Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: maximum of @10@; sfdp, fdp, neato only- | Dir DirType -- ^ /Valid for/: E; /Default/: @'Forward'@ (directed), @'NoDir'@ (undirected)- | DirEdgeConstraints DEConstraints -- ^ /Valid for/: G; /Default/: @'NoConstraints'@; /Parsing Default/: 'EdgeConstraints'; /Notes/: neato only- | Distortion Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@- | DPI Double -- ^ /Valid for/: G; /Default/: @96.0@, @0.0@; /Notes/: svg, bitmap output only; \"resolution\" is a synonym- | EdgeURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only- | EdgeTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only- | EdgeTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only- | Epsilon Double -- ^ /Valid for/: G; /Default/: @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@); /Notes/: neato only- | ESep DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 3@; /Notes/: not dot- | FillColor ColorList -- ^ /Valid for/: NEC; /Default/: @['WC' ('X11Color' 'LightGray') Nothing]@ (nodes), @['WC' ('X11Color' 'Black') Nothing]@ (clusters)- | FixedSize Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'- | FontColor Color -- ^ /Valid for/: ENGC; /Default/: @'X11Color' 'Black'@- | FontName Text -- ^ /Valid for/: ENGC; /Default/: @\"Times-Roman\"@- | FontNames SVGFontNames -- ^ /Valid for/: G; /Default/: @'SvgNames'@; /Notes/: svg only- | FontPath Paths -- ^ /Valid for/: G; /Default/: system dependent- | FontSize Double -- ^ /Valid for/: ENGC; /Default/: @14.0@; /Minimum/: @1.0@- | ForceLabels Bool -- ^ /Valid for/: G; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: only for 'XLabel' attributes, requires Graphviz >= 2.29.0- | GradientAngle Int -- ^ /Valid for/: NCG; /Default/: 0; /Notes/: requires Graphviz >= 2.29.0- | Group Text -- ^ /Valid for/: N; /Default/: @\"\"@; /Notes/: dot only- | HeadURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only- | Head_LP Point -- ^ /Valid for/: E; /Notes/: write only, requires Graphviz >= 2.30.0- | HeadClip Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'- | HeadLabel Label -- ^ /Valid for/: E; /Default/: @'StrLabel' \"\"@- | HeadPort PortPos -- ^ /Valid for/: E; /Default/: @'CompassPoint' 'CenterPoint'@- | HeadTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only- | HeadTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only- | Height Double -- ^ /Valid for/: N; /Default/: @0.5@; /Minimum/: @0.02@- | ID EscString -- ^ /Valid for/: GNE; /Default/: @\"\"@; /Notes/: svg, postscript, map only- | Image Text -- ^ /Valid for/: N; /Default/: @\"\"@- | ImagePath Paths -- ^ /Valid for/: G; /Default/: @'Paths' []@; /Notes/: Printing and parsing is OS-specific, requires Graphviz >= 2.29.0- | ImageScale ScaleType -- ^ /Valid for/: N; /Default/: @'NoScale'@; /Parsing Default/: 'UniformScale'- | Label Label -- ^ /Valid for/: ENGC; /Default/: @'StrLabel' \"\\N\"@ (nodes), @'StrLabel' \"\"@ (otherwise)- | LabelURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only- | LabelScheme LabelScheme -- ^ /Valid for/: G; /Default/: @'NotEdgeLabel'@; /Notes/: sfdp only, requires Graphviz >= 2.28.0- | LabelAngle Double -- ^ /Valid for/: E; /Default/: @-25.0@; /Minimum/: @-180.0@- | LabelDistance Double -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0.0@- | LabelFloat Bool -- ^ /Valid for/: E; /Default/: @'False'@; /Parsing Default/: 'True'- | LabelFontColor Color -- ^ /Valid for/: E; /Default/: @'X11Color' 'Black'@- | LabelFontName Text -- ^ /Valid for/: E; /Default/: @\"Times-Roman\"@- | LabelFontSize Double -- ^ /Valid for/: E; /Default/: @14.0@; /Minimum/: @1.0@- | LabelJust Justification -- ^ /Valid for/: GC; /Default/: @'JCenter'@- | LabelLoc VerticalPlacement -- ^ /Valid for/: GCN; /Default/: @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)- | LabelTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only- | LabelTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only- | Landscape Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'- | Layer LayerRange -- ^ /Valid for/: EN; /Default/: @[]@- | LayerListSep LayerListSep -- ^ /Valid for/: G; /Default/: @'LLSep' \",\"@; /Notes/: requires Graphviz >= 2.30.0- | Layers LayerList -- ^ /Valid for/: G; /Default/: @'LL' []@- | LayerSelect LayerRange -- ^ /Valid for/: G; /Default/: @[]@- | LayerSep LayerSep -- ^ /Valid for/: G; /Default/: @'LSep' \" :\t\"@- | Layout GraphvizCommand -- ^ /Valid for/: G- | Len Double -- ^ /Valid for/: E; /Default/: @1.0@ (neato), @0.3@ (fdp); /Notes/: fdp, neato only- | Levels Int -- ^ /Valid for/: G; /Default/: @'maxBound'@; /Minimum/: @0@; /Notes/: sfdp only- | LevelsGap Double -- ^ /Valid for/: G; /Default/: @0.0@; /Notes/: neato only- | LHead Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: dot only- | LHeight Double -- ^ /Valid for/: GC; /Notes/: write only, requires Graphviz >= 2.28.0- | LPos Point -- ^ /Valid for/: EGC; /Notes/: write only- | LTail Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: dot only- | LWidth Double -- ^ /Valid for/: GC; /Notes/: write only, requires Graphviz >= 2.28.0- | Margin DPoint -- ^ /Valid for/: NG; /Default/: device dependent- | MaxIter Int -- ^ /Valid for/: G; /Default/: @100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp); /Notes/: fdp, neato only- | MCLimit Double -- ^ /Valid for/: G; /Default/: @1.0@; /Notes/: dot only- | MinDist Double -- ^ /Valid for/: G; /Default/: @1.0@; /Minimum/: @0.0@; /Notes/: circo only- | MinLen Int -- ^ /Valid for/: E; /Default/: @1@; /Minimum/: @0@; /Notes/: dot only- | Mode ModeType -- ^ /Valid for/: G; /Default/: @'Major'@; /Notes/: neato only- | Model Model -- ^ /Valid for/: G; /Default/: @'ShortPath'@; /Notes/: neato only- | Mosek Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: neato only; requires the Mosek software- | NodeSep Double -- ^ /Valid for/: G; /Default/: @0.25@; /Minimum/: @0.02@; /Notes/: dot only- | NoJustify Bool -- ^ /Valid for/: GCNE; /Default/: @'False'@; /Parsing Default/: 'True'- | Normalize Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: not dot- | Nslimit Double -- ^ /Valid for/: G; /Notes/: dot only- | Nslimit1 Double -- ^ /Valid for/: G; /Notes/: dot only- | Ordering Order -- ^ /Valid for/: GN; /Default/: none; /Notes/: dot only- | Orientation Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @360.0@- | OutputOrder OutputMode -- ^ /Valid for/: G; /Default/: @'BreadthFirst'@- | Overlap Overlap -- ^ /Valid for/: G; /Default/: @'KeepOverlaps'@; /Parsing Default/: 'KeepOverlaps'; /Notes/: not dot- | OverlapScaling Double -- ^ /Valid for/: G; /Default/: @-4@; /Minimum/: @-1.0e10@; /Notes/: prism only- | Pack Pack -- ^ /Valid for/: G; /Default/: @'DontPack'@; /Parsing Default/: 'DoPack'; /Notes/: not dot- | PackMode PackMode -- ^ /Valid for/: G; /Default/: @'PackNode'@; /Notes/: not dot- | Pad DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 0.0555@ (4 points)- | Page Point -- ^ /Valid for/: G- | PageDir PageDir -- ^ /Valid for/: G; /Default/: @'Bl'@- | PenColor Color -- ^ /Valid for/: C; /Default/: @'X11Color' 'Black'@- | PenWidth Double -- ^ /Valid for/: CNE; /Default/: @1.0@; /Minimum/: @0.0@- | Peripheries Int -- ^ /Valid for/: NC; /Default/: shape default (nodes), @1@ (clusters); /Minimum/: 0- | Pin Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: fdp, neato only- | Pos Pos -- ^ /Valid for/: EN- | QuadTree QuadType -- ^ /Valid for/: G; /Default/: @'NormalQT'@; /Parsing Default/: 'NormalQT'; /Notes/: sfdp only- | Quantum Double -- ^ /Valid for/: G; /Default/: @0.0@; /Minimum/: @0.0@- | Rank RankType -- ^ /Valid for/: S; /Notes/: dot only- | RankDir RankDir -- ^ /Valid for/: G; /Default/: @'FromTop'@; /Notes/: dot only- | RankSep [Double] -- ^ /Valid for/: G; /Default/: @[0.5]@ (dot), @[1.0]@ (twopi); /Minimum/: [0.02]; /Notes/: twopi, dot only- | Ratio Ratios -- ^ /Valid for/: G- | Rects [Rect] -- ^ /Valid for/: N; /Notes/: write only- | Regular Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'- | ReMinCross Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: dot only- | RepulsiveForce Double -- ^ /Valid for/: G; /Default/: @1.0@; /Minimum/: @0.0@; /Notes/: sfdp only- | Root Root -- ^ /Valid for/: GN; /Default/: @'NodeName' \"\"@ (graphs), @'NotCentral'@ (nodes); /Parsing Default/: 'IsCentral'; /Notes/: circo, twopi only- | Rotate Int -- ^ /Valid for/: G; /Default/: @0@- | Rotation Double -- ^ /Valid for/: G; /Default/: @0@; /Notes/: sfdp only, requires Graphviz >= 2.28.0- | SameHead Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: dot only- | SameTail Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: dot only- | SamplePoints Int -- ^ /Valid for/: N; /Default/: @8@ (output), @20@ (overlap and image maps)- | Scale DPoint -- ^ /Valid for/: G; /Notes/: twopi only, requires Graphviz >= 2.28.0- | SearchSize Int -- ^ /Valid for/: G; /Default/: @30@; /Notes/: dot only- | Sep DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 4@; /Notes/: not dot- | Shape Shape -- ^ /Valid for/: N; /Default/: @'Ellipse'@- | ShowBoxes Int -- ^ /Valid for/: ENG; /Default/: @0@; /Minimum/: @0@; /Notes/: dot only; used for debugging by printing PostScript guide boxes- | Sides Int -- ^ /Valid for/: N; /Default/: @4@; /Minimum/: @0@- | Size GraphSize -- ^ /Valid for/: G- | Skew Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@- | Smoothing SmoothType -- ^ /Valid for/: G; /Default/: @'NoSmooth'@; /Notes/: sfdp only- | SortV Word16 -- ^ /Valid for/: GCN; /Default/: @0@; /Minimum/: @0@- | Splines EdgeType -- ^ /Valid for/: G; /Default/: @'SplineEdges'@ (dot), @'LineEdges'@ (other); /Parsing Default/: 'SplineEdges'- | Start StartType -- ^ /Valid for/: G; /Default/: @'StartStyleSeed' 'RandomStyle' seed@ for some unknown fixed seed.; /Notes/: fdp, neato only- | Style [StyleItem] -- ^ /Valid for/: ENC- | StyleSheet Text -- ^ /Valid for/: G; /Default/: @\"\"@; /Notes/: svg only- | TailURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only- | Tail_LP Point -- ^ /Valid for/: E; /Notes/: write only- | TailClip Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'- | TailLabel Label -- ^ /Valid for/: E; /Default/: @'StrLabel' \"\"@- | TailPort PortPos -- ^ /Valid for/: E; /Default/: @'CompassPoint' 'CenterPoint'@- | TailTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only- | TailTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only- | Target EscString -- ^ /Valid for/: ENGC; /Default/: none; /Notes/: svg, map only- | Tooltip EscString -- ^ /Valid for/: NEC; /Default/: @\"\"@; /Notes/: svg, cmap only- | TrueColor Bool -- ^ /Valid for/: G; /Parsing Default/: 'True'; /Notes/: bitmap output only- | Vertices [Point] -- ^ /Valid for/: N; /Notes/: write only- | ViewPort ViewPort -- ^ /Valid for/: G; /Default/: none- | VoroMargin Double -- ^ /Valid for/: G; /Default/: @0.05@; /Minimum/: @0.0@; /Notes/: not dot- | Weight Double -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0@ (dot), @1@ (neato,fdp,sfdp)- | Width Double -- ^ /Valid for/: N; /Default/: @0.75@; /Minimum/: @0.01@- | XLabel Label -- ^ /Valid for/: EN; /Default/: @'StrLabel' \"\"@; /Notes/: requires Graphviz >= 2.29.0- | XLP Point -- ^ /Valid for/: EN; /Notes/: write only, requires Graphviz >= 2.29.0- | UnknownAttribute AttributeName Text -- ^ /Valid for/: Assumed valid for all; the fields are 'Attribute' name and value respectively.- deriving (Eq, Ord, Show, Read)--type Attributes = [Attribute]---- | The name for an UnknownAttribute; must satisfy 'validUnknown'.-type AttributeName = Text--instance PrintDot Attribute where- unqtDot (Damping v) = printField "Damping" v- unqtDot (K v) = printField "K" v- unqtDot (URL v) = printField "URL" v- unqtDot (Area v) = printField "area" v- unqtDot (ArrowHead v) = printField "arrowhead" v- unqtDot (ArrowSize v) = printField "arrowsize" v- unqtDot (ArrowTail v) = printField "arrowtail" v- unqtDot (Aspect v) = printField "aspect" v- unqtDot (BoundingBox v) = printField "bb" v- unqtDot (BgColor v) = printField "bgcolor" v- unqtDot (Center v) = printField "center" v- unqtDot (ClusterRank v) = printField "clusterrank" v- unqtDot (Color v) = printField "color" v- unqtDot (ColorScheme v) = printField "colorscheme" v- unqtDot (Comment v) = printField "comment" v- unqtDot (Compound v) = printField "compound" v- unqtDot (Concentrate v) = printField "concentrate" v- unqtDot (Constraint v) = printField "constraint" v- unqtDot (Decorate v) = printField "decorate" v- unqtDot (DefaultDist v) = printField "defaultdist" v- unqtDot (Dim v) = printField "dim" v- unqtDot (Dimen v) = printField "dimen" v- unqtDot (Dir v) = printField "dir" v- unqtDot (DirEdgeConstraints v) = printField "diredgeconstraints" v- unqtDot (Distortion v) = printField "distortion" v- unqtDot (DPI v) = printField "dpi" v- unqtDot (EdgeURL v) = printField "edgeURL" v- unqtDot (EdgeTarget v) = printField "edgetarget" v- unqtDot (EdgeTooltip v) = printField "edgetooltip" v- unqtDot (Epsilon v) = printField "epsilon" v- unqtDot (ESep v) = printField "esep" v- unqtDot (FillColor v) = printField "fillcolor" v- unqtDot (FixedSize v) = printField "fixedsize" v- unqtDot (FontColor v) = printField "fontcolor" v- unqtDot (FontName v) = printField "fontname" v- unqtDot (FontNames v) = printField "fontnames" v- unqtDot (FontPath v) = printField "fontpath" v- unqtDot (FontSize v) = printField "fontsize" v- unqtDot (ForceLabels v) = printField "forcelabels" v- unqtDot (GradientAngle v) = printField "gradientangle" v- unqtDot (Group v) = printField "group" v- unqtDot (HeadURL v) = printField "headURL" v- unqtDot (Head_LP v) = printField "head_lp" v- unqtDot (HeadClip v) = printField "headclip" v- unqtDot (HeadLabel v) = printField "headlabel" v- unqtDot (HeadPort v) = printField "headport" v- unqtDot (HeadTarget v) = printField "headtarget" v- unqtDot (HeadTooltip v) = printField "headtooltip" v- unqtDot (Height v) = printField "height" v- unqtDot (ID v) = printField "id" v- unqtDot (Image v) = printField "image" v- unqtDot (ImagePath v) = printField "imagepath" v- unqtDot (ImageScale v) = printField "imagescale" v- unqtDot (Label v) = printField "label" v- unqtDot (LabelURL v) = printField "labelURL" v- unqtDot (LabelScheme v) = printField "label_scheme" v- unqtDot (LabelAngle v) = printField "labelangle" v- unqtDot (LabelDistance v) = printField "labeldistance" v- unqtDot (LabelFloat v) = printField "labelfloat" v- unqtDot (LabelFontColor v) = printField "labelfontcolor" v- unqtDot (LabelFontName v) = printField "labelfontname" v- unqtDot (LabelFontSize v) = printField "labelfontsize" v- unqtDot (LabelJust v) = printField "labeljust" v- unqtDot (LabelLoc v) = printField "labelloc" v- unqtDot (LabelTarget v) = printField "labeltarget" v- unqtDot (LabelTooltip v) = printField "labeltooltip" v- unqtDot (Landscape v) = printField "landscape" v- unqtDot (Layer v) = printField "layer" v- unqtDot (LayerListSep v) = printField "layerlistsep" v- unqtDot (Layers v) = printField "layers" v- unqtDot (LayerSelect v) = printField "layerselect" v- unqtDot (LayerSep v) = printField "layersep" v- unqtDot (Layout v) = printField "layout" v- unqtDot (Len v) = printField "len" v- unqtDot (Levels v) = printField "levels" v- unqtDot (LevelsGap v) = printField "levelsgap" v- unqtDot (LHead v) = printField "lhead" v- unqtDot (LHeight v) = printField "LHeight" v- unqtDot (LPos v) = printField "lp" v- unqtDot (LTail v) = printField "ltail" v- unqtDot (LWidth v) = printField "lwidth" v- unqtDot (Margin v) = printField "margin" v- unqtDot (MaxIter v) = printField "maxiter" v- unqtDot (MCLimit v) = printField "mclimit" v- unqtDot (MinDist v) = printField "mindist" v- unqtDot (MinLen v) = printField "minlen" v- unqtDot (Mode v) = printField "mode" v- unqtDot (Model v) = printField "model" v- unqtDot (Mosek v) = printField "mosek" v- unqtDot (NodeSep v) = printField "nodesep" v- unqtDot (NoJustify v) = printField "nojustify" v- unqtDot (Normalize v) = printField "normalize" v- unqtDot (Nslimit v) = printField "nslimit" v- unqtDot (Nslimit1 v) = printField "nslimit1" v- unqtDot (Ordering v) = printField "ordering" v- unqtDot (Orientation v) = printField "orientation" v- unqtDot (OutputOrder v) = printField "outputorder" v- unqtDot (Overlap v) = printField "overlap" v- unqtDot (OverlapScaling v) = printField "overlap_scaling" v- unqtDot (Pack v) = printField "pack" v- unqtDot (PackMode v) = printField "packmode" v- unqtDot (Pad v) = printField "pad" v- unqtDot (Page v) = printField "page" v- unqtDot (PageDir v) = printField "pagedir" v- unqtDot (PenColor v) = printField "pencolor" v- unqtDot (PenWidth v) = printField "penwidth" v- unqtDot (Peripheries v) = printField "peripheries" v- unqtDot (Pin v) = printField "pin" v- unqtDot (Pos v) = printField "pos" v- unqtDot (QuadTree v) = printField "quadtree" v- unqtDot (Quantum v) = printField "quantum" v- unqtDot (Rank v) = printField "rank" v- unqtDot (RankDir v) = printField "rankdir" v- unqtDot (RankSep v) = printField "ranksep" v- unqtDot (Ratio v) = printField "ratio" v- unqtDot (Rects v) = printField "rects" v- unqtDot (Regular v) = printField "regular" v- unqtDot (ReMinCross v) = printField "remincross" v- unqtDot (RepulsiveForce v) = printField "repulsiveforce" v- unqtDot (Root v) = printField "root" v- unqtDot (Rotate v) = printField "rotate" v- unqtDot (Rotation v) = printField "rotation" v- unqtDot (SameHead v) = printField "samehead" v- unqtDot (SameTail v) = printField "sametail" v- unqtDot (SamplePoints v) = printField "samplepoints" v- unqtDot (Scale v) = printField "scale" v- unqtDot (SearchSize v) = printField "searchsize" v- unqtDot (Sep v) = printField "sep" v- unqtDot (Shape v) = printField "shape" v- unqtDot (ShowBoxes v) = printField "showboxes" v- unqtDot (Sides v) = printField "sides" v- unqtDot (Size v) = printField "size" v- unqtDot (Skew v) = printField "skew" v- unqtDot (Smoothing v) = printField "smoothing" v- unqtDot (SortV v) = printField "sortv" v- unqtDot (Splines v) = printField "splines" v- unqtDot (Start v) = printField "start" v- unqtDot (Style v) = printField "style" v- unqtDot (StyleSheet v) = printField "stylesheet" v- unqtDot (TailURL v) = printField "tailURL" v- unqtDot (Tail_LP v) = printField "tail_lp" v- unqtDot (TailClip v) = printField "tailclip" v- unqtDot (TailLabel v) = printField "taillabel" v- unqtDot (TailPort v) = printField "tailport" v- unqtDot (TailTarget v) = printField "tailtarget" v- unqtDot (TailTooltip v) = printField "tailtooltip" v- unqtDot (Target v) = printField "target" v- unqtDot (Tooltip v) = printField "tooltip" v- unqtDot (TrueColor v) = printField "truecolor" v- unqtDot (Vertices v) = printField "vertices" v- unqtDot (ViewPort v) = printField "viewport" v- unqtDot (VoroMargin v) = printField "voro_margin" v- unqtDot (Weight v) = printField "weight" v- unqtDot (Width v) = printField "width" v- unqtDot (XLabel v) = printField "xlabel" v- unqtDot (XLP v) = printField "xlp" v- unqtDot (UnknownAttribute a v) = toDot a <> equals <> toDot v-- listToDot = unqtListToDot--instance ParseDot Attribute where- parseUnqt = stringParse (concat [ parseField Damping "Damping"- , parseField K "K"- , parseFields URL ["URL", "href"]- , parseField Area "area"- , parseField ArrowHead "arrowhead"- , parseField ArrowSize "arrowsize"- , parseField ArrowTail "arrowtail"- , parseField Aspect "aspect"- , parseField BoundingBox "bb"- , parseField BgColor "bgcolor"- , parseFieldBool Center "center"- , parseField ClusterRank "clusterrank"- , parseField Color "color"- , parseField ColorScheme "colorscheme"- , parseField Comment "comment"- , parseFieldBool Compound "compound"- , parseFieldBool Concentrate "concentrate"- , parseFieldBool Constraint "constraint"- , parseFieldBool Decorate "decorate"- , parseField DefaultDist "defaultdist"- , parseField Dim "dim"- , parseField Dimen "dimen"- , parseField Dir "dir"- , parseFieldDef DirEdgeConstraints EdgeConstraints "diredgeconstraints"- , parseField Distortion "distortion"- , parseFields DPI ["dpi", "resolution"]- , parseFields EdgeURL ["edgeURL", "edgehref"]- , parseField EdgeTarget "edgetarget"- , parseField EdgeTooltip "edgetooltip"- , parseField Epsilon "epsilon"- , parseField ESep "esep"- , parseField FillColor "fillcolor"- , parseFieldBool FixedSize "fixedsize"- , parseField FontColor "fontcolor"- , parseField FontName "fontname"- , parseField FontNames "fontnames"- , parseField FontPath "fontpath"- , parseField FontSize "fontsize"- , parseFieldBool ForceLabels "forcelabels"- , parseField GradientAngle "gradientangle"- , parseField Group "group"- , parseFields HeadURL ["headURL", "headhref"]- , parseField Head_LP "head_lp"- , parseFieldBool HeadClip "headclip"- , parseField HeadLabel "headlabel"- , parseField HeadPort "headport"- , parseField HeadTarget "headtarget"- , parseField HeadTooltip "headtooltip"- , parseField Height "height"- , parseField ID "id"- , parseField Image "image"- , parseField ImagePath "imagepath"- , parseFieldDef ImageScale UniformScale "imagescale"- , parseField Label "label"- , parseFields LabelURL ["labelURL", "labelhref"]- , parseField LabelScheme "label_scheme"- , parseField LabelAngle "labelangle"- , parseField LabelDistance "labeldistance"- , parseFieldBool LabelFloat "labelfloat"- , parseField LabelFontColor "labelfontcolor"- , parseField LabelFontName "labelfontname"- , parseField LabelFontSize "labelfontsize"- , parseField LabelJust "labeljust"- , parseField LabelLoc "labelloc"- , parseField LabelTarget "labeltarget"- , parseField LabelTooltip "labeltooltip"- , parseFieldBool Landscape "landscape"- , parseField Layer "layer"- , parseField LayerListSep "layerlistsep"- , parseField Layers "layers"- , parseField LayerSelect "layerselect"- , parseField LayerSep "layersep"- , parseField Layout "layout"- , parseField Len "len"- , parseField Levels "levels"- , parseField LevelsGap "levelsgap"- , parseField LHead "lhead"- , parseField LHeight "LHeight"- , parseField LPos "lp"- , parseField LTail "ltail"- , parseField LWidth "lwidth"- , parseField Margin "margin"- , parseField MaxIter "maxiter"- , parseField MCLimit "mclimit"- , parseField MinDist "mindist"- , parseField MinLen "minlen"- , parseField Mode "mode"- , parseField Model "model"- , parseFieldBool Mosek "mosek"- , parseField NodeSep "nodesep"- , parseFieldBool NoJustify "nojustify"- , parseFieldBool Normalize "normalize"- , parseField Nslimit "nslimit"- , parseField Nslimit1 "nslimit1"- , parseField Ordering "ordering"- , parseField Orientation "orientation"- , parseField OutputOrder "outputorder"- , parseFieldDef Overlap KeepOverlaps "overlap"- , parseField OverlapScaling "overlap_scaling"- , parseFieldDef Pack DoPack "pack"- , parseField PackMode "packmode"- , parseField Pad "pad"- , parseField Page "page"- , parseField PageDir "pagedir"- , parseField PenColor "pencolor"- , parseField PenWidth "penwidth"- , parseField Peripheries "peripheries"- , parseFieldBool Pin "pin"- , parseField Pos "pos"- , parseFieldDef QuadTree NormalQT "quadtree"- , parseField Quantum "quantum"- , parseField Rank "rank"- , parseField RankDir "rankdir"- , parseField RankSep "ranksep"- , parseField Ratio "ratio"- , parseField Rects "rects"- , parseFieldBool Regular "regular"- , parseFieldBool ReMinCross "remincross"- , parseField RepulsiveForce "repulsiveforce"- , parseFieldDef Root IsCentral "root"- , parseField Rotate "rotate"- , parseField Rotation "rotation"- , parseField SameHead "samehead"- , parseField SameTail "sametail"- , parseField SamplePoints "samplepoints"- , parseField Scale "scale"- , parseField SearchSize "searchsize"- , parseField Sep "sep"- , parseField Shape "shape"- , parseField ShowBoxes "showboxes"- , parseField Sides "sides"- , parseField Size "size"- , parseField Skew "skew"- , parseField Smoothing "smoothing"- , parseField SortV "sortv"- , parseFieldDef Splines SplineEdges "splines"- , parseField Start "start"- , parseField Style "style"- , parseField StyleSheet "stylesheet"- , parseFields TailURL ["tailURL", "tailhref"]- , parseField Tail_LP "tail_lp"- , parseFieldBool TailClip "tailclip"- , parseField TailLabel "taillabel"- , parseField TailPort "tailport"- , parseField TailTarget "tailtarget"- , parseField TailTooltip "tailtooltip"- , parseField Target "target"- , parseField Tooltip "tooltip"- , parseFieldBool TrueColor "truecolor"- , parseField Vertices "vertices"- , parseField ViewPort "viewport"- , parseField VoroMargin "voro_margin"- , parseField Weight "weight"- , parseField Width "width"- , parseField XLabel "xlabel"- , parseField XLP "xlp"- ])- `onFail`- do attrName <- stringBlock- liftEqParse ("UnknownAttribute (" ++ T.unpack attrName ++ ")")- (UnknownAttribute attrName)-- parse = parseUnqt-- parseList = parseUnqtList---- | Determine if this 'Attribute' is valid for use with Graphs.-usedByGraphs :: Attribute -> Bool-usedByGraphs Damping{} = True-usedByGraphs K{} = True-usedByGraphs URL{} = True-usedByGraphs Aspect{} = True-usedByGraphs BoundingBox{} = True-usedByGraphs BgColor{} = True-usedByGraphs Center{} = True-usedByGraphs ClusterRank{} = True-usedByGraphs ColorScheme{} = True-usedByGraphs Comment{} = True-usedByGraphs Compound{} = True-usedByGraphs Concentrate{} = True-usedByGraphs DefaultDist{} = True-usedByGraphs Dim{} = True-usedByGraphs Dimen{} = True-usedByGraphs DirEdgeConstraints{} = True-usedByGraphs DPI{} = True-usedByGraphs Epsilon{} = True-usedByGraphs ESep{} = True-usedByGraphs FontColor{} = True-usedByGraphs FontName{} = True-usedByGraphs FontNames{} = True-usedByGraphs FontPath{} = True-usedByGraphs FontSize{} = True-usedByGraphs ForceLabels{} = True-usedByGraphs GradientAngle{} = True-usedByGraphs ID{} = True-usedByGraphs ImagePath{} = True-usedByGraphs Label{} = True-usedByGraphs LabelScheme{} = True-usedByGraphs LabelJust{} = True-usedByGraphs LabelLoc{} = True-usedByGraphs Landscape{} = True-usedByGraphs LayerListSep{} = True-usedByGraphs Layers{} = True-usedByGraphs LayerSelect{} = True-usedByGraphs LayerSep{} = True-usedByGraphs Layout{} = True-usedByGraphs Levels{} = True-usedByGraphs LevelsGap{} = True-usedByGraphs LHeight{} = True-usedByGraphs LPos{} = True-usedByGraphs LWidth{} = True-usedByGraphs Margin{} = True-usedByGraphs MaxIter{} = True-usedByGraphs MCLimit{} = True-usedByGraphs MinDist{} = True-usedByGraphs Mode{} = True-usedByGraphs Model{} = True-usedByGraphs Mosek{} = True-usedByGraphs NodeSep{} = True-usedByGraphs NoJustify{} = True-usedByGraphs Normalize{} = True-usedByGraphs Nslimit{} = True-usedByGraphs Nslimit1{} = True-usedByGraphs Ordering{} = True-usedByGraphs OutputOrder{} = True-usedByGraphs Overlap{} = True-usedByGraphs OverlapScaling{} = True-usedByGraphs Pack{} = True-usedByGraphs PackMode{} = True-usedByGraphs Pad{} = True-usedByGraphs Page{} = True-usedByGraphs PageDir{} = True-usedByGraphs QuadTree{} = True-usedByGraphs Quantum{} = True-usedByGraphs RankDir{} = True-usedByGraphs RankSep{} = True-usedByGraphs Ratio{} = True-usedByGraphs ReMinCross{} = True-usedByGraphs RepulsiveForce{} = True-usedByGraphs Root{} = True-usedByGraphs Rotate{} = True-usedByGraphs Rotation{} = True-usedByGraphs Scale{} = True-usedByGraphs SearchSize{} = True-usedByGraphs Sep{} = True-usedByGraphs ShowBoxes{} = True-usedByGraphs Size{} = True-usedByGraphs Smoothing{} = True-usedByGraphs SortV{} = True-usedByGraphs Splines{} = True-usedByGraphs Start{} = True-usedByGraphs StyleSheet{} = True-usedByGraphs Target{} = True-usedByGraphs TrueColor{} = True-usedByGraphs ViewPort{} = True-usedByGraphs VoroMargin{} = True-usedByGraphs UnknownAttribute{} = True-usedByGraphs _ = False---- | Determine if this 'Attribute' is valid for use with Clusters.-usedByClusters :: Attribute -> Bool-usedByClusters K{} = True-usedByClusters URL{} = True-usedByClusters Area{} = True-usedByClusters BgColor{} = True-usedByClusters Color{} = True-usedByClusters ColorScheme{} = True-usedByClusters FillColor{} = True-usedByClusters FontColor{} = True-usedByClusters FontName{} = True-usedByClusters FontSize{} = True-usedByClusters GradientAngle{} = True-usedByClusters Label{} = True-usedByClusters LabelJust{} = True-usedByClusters LabelLoc{} = True-usedByClusters LHeight{} = True-usedByClusters LPos{} = True-usedByClusters LWidth{} = True-usedByClusters NoJustify{} = True-usedByClusters PenColor{} = True-usedByClusters PenWidth{} = True-usedByClusters Peripheries{} = True-usedByClusters Rank{} = True-usedByClusters SortV{} = True-usedByClusters Style{} = True-usedByClusters Target{} = True-usedByClusters Tooltip{} = True-usedByClusters UnknownAttribute{} = True-usedByClusters _ = False---- | Determine if this 'Attribute' is valid for use with SubGraphs.-usedBySubGraphs :: Attribute -> Bool-usedBySubGraphs Rank{} = True-usedBySubGraphs UnknownAttribute{} = True-usedBySubGraphs _ = False---- | Determine if this 'Attribute' is valid for use with Nodes.-usedByNodes :: Attribute -> Bool-usedByNodes URL{} = True-usedByNodes Area{} = True-usedByNodes Color{} = True-usedByNodes ColorScheme{} = True-usedByNodes Comment{} = True-usedByNodes Distortion{} = True-usedByNodes FillColor{} = True-usedByNodes FixedSize{} = True-usedByNodes FontColor{} = True-usedByNodes FontName{} = True-usedByNodes FontSize{} = True-usedByNodes GradientAngle{} = True-usedByNodes Group{} = True-usedByNodes Height{} = True-usedByNodes ID{} = True-usedByNodes Image{} = True-usedByNodes ImageScale{} = True-usedByNodes Label{} = True-usedByNodes LabelLoc{} = True-usedByNodes Layer{} = True-usedByNodes Margin{} = True-usedByNodes NoJustify{} = True-usedByNodes Ordering{} = True-usedByNodes Orientation{} = True-usedByNodes PenWidth{} = True-usedByNodes Peripheries{} = True-usedByNodes Pin{} = True-usedByNodes Pos{} = True-usedByNodes Rects{} = True-usedByNodes Regular{} = True-usedByNodes Root{} = True-usedByNodes SamplePoints{} = True-usedByNodes Shape{} = True-usedByNodes ShowBoxes{} = True-usedByNodes Sides{} = True-usedByNodes Skew{} = True-usedByNodes SortV{} = True-usedByNodes Style{} = True-usedByNodes Target{} = True-usedByNodes Tooltip{} = True-usedByNodes Vertices{} = True-usedByNodes Width{} = True-usedByNodes XLabel{} = True-usedByNodes XLP{} = True-usedByNodes UnknownAttribute{} = True-usedByNodes _ = False---- | Determine if this 'Attribute' is valid for use with Edges.-usedByEdges :: Attribute -> Bool-usedByEdges URL{} = True-usedByEdges ArrowHead{} = True-usedByEdges ArrowSize{} = True-usedByEdges ArrowTail{} = True-usedByEdges Color{} = True-usedByEdges ColorScheme{} = True-usedByEdges Comment{} = True-usedByEdges Constraint{} = True-usedByEdges Decorate{} = True-usedByEdges Dir{} = True-usedByEdges EdgeURL{} = True-usedByEdges EdgeTarget{} = True-usedByEdges EdgeTooltip{} = True-usedByEdges FillColor{} = True-usedByEdges FontColor{} = True-usedByEdges FontName{} = True-usedByEdges FontSize{} = True-usedByEdges HeadURL{} = True-usedByEdges Head_LP{} = True-usedByEdges HeadClip{} = True-usedByEdges HeadLabel{} = True-usedByEdges HeadPort{} = True-usedByEdges HeadTarget{} = True-usedByEdges HeadTooltip{} = True-usedByEdges ID{} = True-usedByEdges Label{} = True-usedByEdges LabelURL{} = True-usedByEdges LabelAngle{} = True-usedByEdges LabelDistance{} = True-usedByEdges LabelFloat{} = True-usedByEdges LabelFontColor{} = True-usedByEdges LabelFontName{} = True-usedByEdges LabelFontSize{} = True-usedByEdges LabelTarget{} = True-usedByEdges LabelTooltip{} = True-usedByEdges Layer{} = True-usedByEdges Len{} = True-usedByEdges LHead{} = True-usedByEdges LPos{} = True-usedByEdges LTail{} = True-usedByEdges MinLen{} = True-usedByEdges NoJustify{} = True-usedByEdges PenWidth{} = True-usedByEdges Pos{} = True-usedByEdges SameHead{} = True-usedByEdges SameTail{} = True-usedByEdges ShowBoxes{} = True-usedByEdges Style{} = True-usedByEdges TailURL{} = True-usedByEdges Tail_LP{} = True-usedByEdges TailClip{} = True-usedByEdges TailLabel{} = True-usedByEdges TailPort{} = True-usedByEdges TailTarget{} = True-usedByEdges TailTooltip{} = True-usedByEdges Target{} = True-usedByEdges Tooltip{} = True-usedByEdges Weight{} = True-usedByEdges XLabel{} = True-usedByEdges XLP{} = True-usedByEdges UnknownAttribute{} = True-usedByEdges _ = False---- | Determine if two 'Attributes' are the same type of 'Attribute'.-sameAttribute :: Attribute -> Attribute -> Bool-sameAttribute Damping{} Damping{} = True-sameAttribute K{} K{} = True-sameAttribute URL{} URL{} = True-sameAttribute Area{} Area{} = True-sameAttribute ArrowHead{} ArrowHead{} = True-sameAttribute ArrowSize{} ArrowSize{} = True-sameAttribute ArrowTail{} ArrowTail{} = True-sameAttribute Aspect{} Aspect{} = True-sameAttribute BoundingBox{} BoundingBox{} = True-sameAttribute BgColor{} BgColor{} = True-sameAttribute Center{} Center{} = True-sameAttribute ClusterRank{} ClusterRank{} = True-sameAttribute Color{} Color{} = True-sameAttribute ColorScheme{} ColorScheme{} = True-sameAttribute Comment{} Comment{} = True-sameAttribute Compound{} Compound{} = True-sameAttribute Concentrate{} Concentrate{} = True-sameAttribute Constraint{} Constraint{} = True-sameAttribute Decorate{} Decorate{} = True-sameAttribute DefaultDist{} DefaultDist{} = True-sameAttribute Dim{} Dim{} = True-sameAttribute Dimen{} Dimen{} = True-sameAttribute Dir{} Dir{} = True-sameAttribute DirEdgeConstraints{} DirEdgeConstraints{} = True-sameAttribute Distortion{} Distortion{} = True-sameAttribute DPI{} DPI{} = True-sameAttribute EdgeURL{} EdgeURL{} = True-sameAttribute EdgeTarget{} EdgeTarget{} = True-sameAttribute EdgeTooltip{} EdgeTooltip{} = True-sameAttribute Epsilon{} Epsilon{} = True-sameAttribute ESep{} ESep{} = True-sameAttribute FillColor{} FillColor{} = True-sameAttribute FixedSize{} FixedSize{} = True-sameAttribute FontColor{} FontColor{} = True-sameAttribute FontName{} FontName{} = True-sameAttribute FontNames{} FontNames{} = True-sameAttribute FontPath{} FontPath{} = True-sameAttribute FontSize{} FontSize{} = True-sameAttribute ForceLabels{} ForceLabels{} = True-sameAttribute GradientAngle{} GradientAngle{} = True-sameAttribute Group{} Group{} = True-sameAttribute HeadURL{} HeadURL{} = True-sameAttribute Head_LP{} Head_LP{} = True-sameAttribute HeadClip{} HeadClip{} = True-sameAttribute HeadLabel{} HeadLabel{} = True-sameAttribute HeadPort{} HeadPort{} = True-sameAttribute HeadTarget{} HeadTarget{} = True-sameAttribute HeadTooltip{} HeadTooltip{} = True-sameAttribute Height{} Height{} = True-sameAttribute ID{} ID{} = True-sameAttribute Image{} Image{} = True-sameAttribute ImagePath{} ImagePath{} = True-sameAttribute ImageScale{} ImageScale{} = True-sameAttribute Label{} Label{} = True-sameAttribute LabelURL{} LabelURL{} = True-sameAttribute LabelScheme{} LabelScheme{} = True-sameAttribute LabelAngle{} LabelAngle{} = True-sameAttribute LabelDistance{} LabelDistance{} = True-sameAttribute LabelFloat{} LabelFloat{} = True-sameAttribute LabelFontColor{} LabelFontColor{} = True-sameAttribute LabelFontName{} LabelFontName{} = True-sameAttribute LabelFontSize{} LabelFontSize{} = True-sameAttribute LabelJust{} LabelJust{} = True-sameAttribute LabelLoc{} LabelLoc{} = True-sameAttribute LabelTarget{} LabelTarget{} = True-sameAttribute LabelTooltip{} LabelTooltip{} = True-sameAttribute Landscape{} Landscape{} = True-sameAttribute Layer{} Layer{} = True-sameAttribute LayerListSep{} LayerListSep{} = True-sameAttribute Layers{} Layers{} = True-sameAttribute LayerSelect{} LayerSelect{} = True-sameAttribute LayerSep{} LayerSep{} = True-sameAttribute Layout{} Layout{} = True-sameAttribute Len{} Len{} = True-sameAttribute Levels{} Levels{} = True-sameAttribute LevelsGap{} LevelsGap{} = True-sameAttribute LHead{} LHead{} = True-sameAttribute LHeight{} LHeight{} = True-sameAttribute LPos{} LPos{} = True-sameAttribute LTail{} LTail{} = True-sameAttribute LWidth{} LWidth{} = True-sameAttribute Margin{} Margin{} = True-sameAttribute MaxIter{} MaxIter{} = True-sameAttribute MCLimit{} MCLimit{} = True-sameAttribute MinDist{} MinDist{} = True-sameAttribute MinLen{} MinLen{} = True-sameAttribute Mode{} Mode{} = True-sameAttribute Model{} Model{} = True-sameAttribute Mosek{} Mosek{} = True-sameAttribute NodeSep{} NodeSep{} = True-sameAttribute NoJustify{} NoJustify{} = True-sameAttribute Normalize{} Normalize{} = True-sameAttribute Nslimit{} Nslimit{} = True-sameAttribute Nslimit1{} Nslimit1{} = True-sameAttribute Ordering{} Ordering{} = True-sameAttribute Orientation{} Orientation{} = True-sameAttribute OutputOrder{} OutputOrder{} = True-sameAttribute Overlap{} Overlap{} = True-sameAttribute OverlapScaling{} OverlapScaling{} = True-sameAttribute Pack{} Pack{} = True-sameAttribute PackMode{} PackMode{} = True-sameAttribute Pad{} Pad{} = True-sameAttribute Page{} Page{} = True-sameAttribute PageDir{} PageDir{} = True-sameAttribute PenColor{} PenColor{} = True-sameAttribute PenWidth{} PenWidth{} = True-sameAttribute Peripheries{} Peripheries{} = True-sameAttribute Pin{} Pin{} = True-sameAttribute Pos{} Pos{} = True-sameAttribute QuadTree{} QuadTree{} = True-sameAttribute Quantum{} Quantum{} = True-sameAttribute Rank{} Rank{} = True-sameAttribute RankDir{} RankDir{} = True-sameAttribute RankSep{} RankSep{} = True-sameAttribute Ratio{} Ratio{} = True-sameAttribute Rects{} Rects{} = True-sameAttribute Regular{} Regular{} = True-sameAttribute ReMinCross{} ReMinCross{} = True-sameAttribute RepulsiveForce{} RepulsiveForce{} = True-sameAttribute Root{} Root{} = True-sameAttribute Rotate{} Rotate{} = True-sameAttribute Rotation{} Rotation{} = True-sameAttribute SameHead{} SameHead{} = True-sameAttribute SameTail{} SameTail{} = True-sameAttribute SamplePoints{} SamplePoints{} = True-sameAttribute Scale{} Scale{} = True-sameAttribute SearchSize{} SearchSize{} = True-sameAttribute Sep{} Sep{} = True-sameAttribute Shape{} Shape{} = True-sameAttribute ShowBoxes{} ShowBoxes{} = True-sameAttribute Sides{} Sides{} = True-sameAttribute Size{} Size{} = True-sameAttribute Skew{} Skew{} = True-sameAttribute Smoothing{} Smoothing{} = True-sameAttribute SortV{} SortV{} = True-sameAttribute Splines{} Splines{} = True-sameAttribute Start{} Start{} = True-sameAttribute Style{} Style{} = True-sameAttribute StyleSheet{} StyleSheet{} = True-sameAttribute TailURL{} TailURL{} = True-sameAttribute Tail_LP{} Tail_LP{} = True-sameAttribute TailClip{} TailClip{} = True-sameAttribute TailLabel{} TailLabel{} = True-sameAttribute TailPort{} TailPort{} = True-sameAttribute TailTarget{} TailTarget{} = True-sameAttribute TailTooltip{} TailTooltip{} = True-sameAttribute Target{} Target{} = True-sameAttribute Tooltip{} Tooltip{} = True-sameAttribute TrueColor{} TrueColor{} = True-sameAttribute Vertices{} Vertices{} = True-sameAttribute ViewPort{} ViewPort{} = True-sameAttribute VoroMargin{} VoroMargin{} = True-sameAttribute Weight{} Weight{} = True-sameAttribute Width{} Width{} = True-sameAttribute XLabel{} XLabel{} = True-sameAttribute XLP{} XLP{} = True-sameAttribute (UnknownAttribute a1 _) (UnknownAttribute a2 _) = a1 == a2-sameAttribute _ _ = False---- | Return the default value for a specific 'Attribute' if possible; graph/cluster values are preferred over node/edge values.-defaultAttributeValue :: Attribute -> Maybe Attribute-defaultAttributeValue Damping{} = Just $ Damping 0.99-defaultAttributeValue K{} = Just $ K 0.3-defaultAttributeValue URL{} = Just $ URL ""-defaultAttributeValue Area{} = Just $ Area 1.0-defaultAttributeValue ArrowHead{} = Just $ ArrowHead normal-defaultAttributeValue ArrowSize{} = Just $ ArrowSize 1.0-defaultAttributeValue ArrowTail{} = Just $ ArrowTail normal-defaultAttributeValue BgColor{} = Just $ BgColor []-defaultAttributeValue Center{} = Just $ Center False-defaultAttributeValue ClusterRank{} = Just $ ClusterRank Local-defaultAttributeValue Color{} = Just $ Color [toWColor Black]-defaultAttributeValue ColorScheme{} = Just $ ColorScheme X11-defaultAttributeValue Comment{} = Just $ Comment ""-defaultAttributeValue Compound{} = Just $ Compound False-defaultAttributeValue Concentrate{} = Just $ Concentrate False-defaultAttributeValue Constraint{} = Just $ Constraint True-defaultAttributeValue Decorate{} = Just $ Decorate False-defaultAttributeValue Dim{} = Just $ Dim 2-defaultAttributeValue Dimen{} = Just $ Dimen 2-defaultAttributeValue DirEdgeConstraints{} = Just $ DirEdgeConstraints NoConstraints-defaultAttributeValue Distortion{} = Just $ Distortion 0.0-defaultAttributeValue DPI{} = Just $ DPI 96.0-defaultAttributeValue EdgeURL{} = Just $ EdgeURL ""-defaultAttributeValue EdgeTooltip{} = Just $ EdgeTooltip ""-defaultAttributeValue ESep{} = Just $ ESep (DVal 3)-defaultAttributeValue FillColor{} = Just $ FillColor [toWColor Black]-defaultAttributeValue FixedSize{} = Just $ FixedSize False-defaultAttributeValue FontColor{} = Just $ FontColor (X11Color Black)-defaultAttributeValue FontName{} = Just $ FontName "Times-Roman"-defaultAttributeValue FontNames{} = Just $ FontNames SvgNames-defaultAttributeValue FontSize{} = Just $ FontSize 14.0-defaultAttributeValue ForceLabels{} = Just $ ForceLabels True-defaultAttributeValue GradientAngle{} = Just $ GradientAngle 0-defaultAttributeValue Group{} = Just $ Group ""-defaultAttributeValue HeadURL{} = Just $ HeadURL ""-defaultAttributeValue HeadClip{} = Just $ HeadClip True-defaultAttributeValue HeadLabel{} = Just $ HeadLabel (StrLabel "")-defaultAttributeValue HeadPort{} = Just $ HeadPort (CompassPoint CenterPoint)-defaultAttributeValue HeadTarget{} = Just $ HeadTarget ""-defaultAttributeValue HeadTooltip{} = Just $ HeadTooltip ""-defaultAttributeValue Height{} = Just $ Height 0.5-defaultAttributeValue ID{} = Just $ ID ""-defaultAttributeValue Image{} = Just $ Image ""-defaultAttributeValue ImagePath{} = Just $ ImagePath (Paths [])-defaultAttributeValue ImageScale{} = Just $ ImageScale NoScale-defaultAttributeValue Label{} = Just $ Label (StrLabel "")-defaultAttributeValue LabelURL{} = Just $ LabelURL ""-defaultAttributeValue LabelScheme{} = Just $ LabelScheme NotEdgeLabel-defaultAttributeValue LabelAngle{} = Just $ LabelAngle (-25.0)-defaultAttributeValue LabelDistance{} = Just $ LabelDistance 1.0-defaultAttributeValue LabelFloat{} = Just $ LabelFloat False-defaultAttributeValue LabelFontColor{} = Just $ LabelFontColor (X11Color Black)-defaultAttributeValue LabelFontName{} = Just $ LabelFontName "Times-Roman"-defaultAttributeValue LabelFontSize{} = Just $ LabelFontSize 14.0-defaultAttributeValue LabelJust{} = Just $ LabelJust JCenter-defaultAttributeValue LabelLoc{} = Just $ LabelLoc VTop-defaultAttributeValue LabelTarget{} = Just $ LabelTarget ""-defaultAttributeValue LabelTooltip{} = Just $ LabelTooltip ""-defaultAttributeValue Landscape{} = Just $ Landscape False-defaultAttributeValue Layer{} = Just $ Layer []-defaultAttributeValue LayerListSep{} = Just $ LayerListSep (LLSep ",")-defaultAttributeValue Layers{} = Just $ Layers (LL [])-defaultAttributeValue LayerSelect{} = Just $ LayerSelect []-defaultAttributeValue LayerSep{} = Just $ LayerSep (LSep " :\t")-defaultAttributeValue Levels{} = Just $ Levels maxBound-defaultAttributeValue LevelsGap{} = Just $ LevelsGap 0.0-defaultAttributeValue LHead{} = Just $ LHead ""-defaultAttributeValue LTail{} = Just $ LTail ""-defaultAttributeValue MCLimit{} = Just $ MCLimit 1.0-defaultAttributeValue MinDist{} = Just $ MinDist 1.0-defaultAttributeValue MinLen{} = Just $ MinLen 1-defaultAttributeValue Mode{} = Just $ Mode Major-defaultAttributeValue Model{} = Just $ Model ShortPath-defaultAttributeValue Mosek{} = Just $ Mosek False-defaultAttributeValue NodeSep{} = Just $ NodeSep 0.25-defaultAttributeValue NoJustify{} = Just $ NoJustify False-defaultAttributeValue Normalize{} = Just $ Normalize False-defaultAttributeValue Orientation{} = Just $ Orientation 0.0-defaultAttributeValue OutputOrder{} = Just $ OutputOrder BreadthFirst-defaultAttributeValue Overlap{} = Just $ Overlap KeepOverlaps-defaultAttributeValue OverlapScaling{} = Just $ OverlapScaling (-4)-defaultAttributeValue Pack{} = Just $ Pack DontPack-defaultAttributeValue PackMode{} = Just $ PackMode PackNode-defaultAttributeValue Pad{} = Just $ Pad (DVal 0.0555)-defaultAttributeValue PageDir{} = Just $ PageDir Bl-defaultAttributeValue PenColor{} = Just $ PenColor (X11Color Black)-defaultAttributeValue PenWidth{} = Just $ PenWidth 1.0-defaultAttributeValue Peripheries{} = Just $ Peripheries 1-defaultAttributeValue Pin{} = Just $ Pin False-defaultAttributeValue QuadTree{} = Just $ QuadTree NormalQT-defaultAttributeValue Quantum{} = Just $ Quantum 0-defaultAttributeValue RankDir{} = Just $ RankDir FromTop-defaultAttributeValue Regular{} = Just $ Regular False-defaultAttributeValue ReMinCross{} = Just $ ReMinCross False-defaultAttributeValue RepulsiveForce{} = Just $ RepulsiveForce 1.0-defaultAttributeValue Root{} = Just $ Root (NodeName "")-defaultAttributeValue Rotate{} = Just $ Rotate 0-defaultAttributeValue Rotation{} = Just $ Rotation 0-defaultAttributeValue SameHead{} = Just $ SameHead ""-defaultAttributeValue SameTail{} = Just $ SameTail ""-defaultAttributeValue SearchSize{} = Just $ SearchSize 30-defaultAttributeValue Sep{} = Just $ Sep (DVal 4)-defaultAttributeValue Shape{} = Just $ Shape Ellipse-defaultAttributeValue ShowBoxes{} = Just $ ShowBoxes 0-defaultAttributeValue Sides{} = Just $ Sides 4-defaultAttributeValue Skew{} = Just $ Skew 0.0-defaultAttributeValue Smoothing{} = Just $ Smoothing NoSmooth-defaultAttributeValue SortV{} = Just $ SortV 0-defaultAttributeValue StyleSheet{} = Just $ StyleSheet ""-defaultAttributeValue TailURL{} = Just $ TailURL ""-defaultAttributeValue TailClip{} = Just $ TailClip True-defaultAttributeValue TailLabel{} = Just $ TailLabel (StrLabel "")-defaultAttributeValue TailPort{} = Just $ TailPort (CompassPoint CenterPoint)-defaultAttributeValue TailTarget{} = Just $ TailTarget ""-defaultAttributeValue TailTooltip{} = Just $ TailTooltip ""-defaultAttributeValue Target{} = Just $ Target ""-defaultAttributeValue Tooltip{} = Just $ Tooltip ""-defaultAttributeValue VoroMargin{} = Just $ VoroMargin 0.05-defaultAttributeValue Weight{} = Just $ Weight 1.0-defaultAttributeValue Width{} = Just $ Width 0.75-defaultAttributeValue XLabel{} = Just $ XLabel (StrLabel "")-defaultAttributeValue _ = Nothing---- | Determine if the provided 'Text' value is a valid name for an 'UnknownAttribute'.-validUnknown :: AttributeName -> Bool-validUnknown txt = T.toLower txt `S.notMember` names- && isIDString txt- where- names = (S.fromList . map T.toLower- $ [ "Damping"- , "K"- , "URL"- , "href"- , "area"- , "arrowhead"- , "arrowsize"- , "arrowtail"- , "aspect"- , "bb"- , "bgcolor"- , "center"- , "clusterrank"- , "color"- , "colorscheme"- , "comment"- , "compound"- , "concentrate"- , "constraint"- , "decorate"- , "defaultdist"- , "dim"- , "dimen"- , "dir"- , "diredgeconstraints"- , "distortion"- , "dpi"- , "resolution"- , "edgeURL"- , "edgehref"- , "edgetarget"- , "edgetooltip"- , "epsilon"- , "esep"- , "fillcolor"- , "fixedsize"- , "fontcolor"- , "fontname"- , "fontnames"- , "fontpath"- , "fontsize"- , "forcelabels"- , "gradientangle"- , "group"- , "headURL"- , "headhref"- , "head_lp"- , "headclip"- , "headlabel"- , "headport"- , "headtarget"- , "headtooltip"- , "height"- , "id"- , "image"- , "imagepath"- , "imagescale"- , "label"- , "labelURL"- , "labelhref"- , "label_scheme"- , "labelangle"- , "labeldistance"- , "labelfloat"- , "labelfontcolor"- , "labelfontname"- , "labelfontsize"- , "labeljust"- , "labelloc"- , "labeltarget"- , "labeltooltip"- , "landscape"- , "layer"- , "layerlistsep"- , "layers"- , "layerselect"- , "layersep"- , "layout"- , "len"- , "levels"- , "levelsgap"- , "lhead"- , "LHeight"- , "lp"- , "ltail"- , "lwidth"- , "margin"- , "maxiter"- , "mclimit"- , "mindist"- , "minlen"- , "mode"- , "model"- , "mosek"- , "nodesep"- , "nojustify"- , "normalize"- , "nslimit"- , "nslimit1"- , "ordering"- , "orientation"- , "outputorder"- , "overlap"- , "overlap_scaling"- , "pack"- , "packmode"- , "pad"- , "page"- , "pagedir"- , "pencolor"- , "penwidth"- , "peripheries"- , "pin"- , "pos"- , "quadtree"- , "quantum"- , "rank"- , "rankdir"- , "ranksep"- , "ratio"- , "rects"- , "regular"- , "remincross"- , "repulsiveforce"- , "root"- , "rotate"- , "rotation"- , "samehead"- , "sametail"- , "samplepoints"- , "scale"- , "searchsize"- , "sep"- , "shape"- , "showboxes"- , "sides"- , "size"- , "skew"- , "smoothing"- , "sortv"- , "splines"- , "start"- , "style"- , "stylesheet"- , "tailURL"- , "tailhref"- , "tail_lp"- , "tailclip"- , "taillabel"- , "tailport"- , "tailtarget"- , "tailtooltip"- , "target"- , "tooltip"- , "truecolor"- , "vertices"- , "viewport"- , "voro_margin"- , "weight"- , "width"- , "xlabel"- , "xlp"- , "charset" -- Defined upstream, just not used here.- ])- `S.union`- keywords-{- Delete to here -}---- | Remove attributes that we don't want to consider:------ * Those that are defaults--- * colorscheme (as the colors embed it anyway)-rmUnwantedAttributes :: Attributes -> Attributes-rmUnwantedAttributes = filter (not . (`any` tests) . flip ($))- where- tests = [isDefault, isColorScheme]-- isDefault a = maybe False (a==) $ defaultAttributeValue a-- isColorScheme ColorScheme{} = True- isColorScheme _ = False---- -------------------------------------------------------------------------------- These parsing combinators are defined here for customisation purposes.--parseField :: (ParseDot a) => (a -> Attribute) -> String- -> [(String, Parse Attribute)]-parseField c fld = [(fld, liftEqParse fld c)]--parseFields :: (ParseDot a) => (a -> Attribute) -> [String]- -> [(String, Parse Attribute)]-parseFields c = concatMap (parseField c)--parseFieldBool :: (Bool -> Attribute) -> String -> [(String, Parse Attribute)]-parseFieldBool = (`parseFieldDef` True)---- | For 'Bool'-like data structures where the presence of the field--- name without a value implies a default value.-parseFieldDef :: (ParseDot a) => (a -> Attribute) -> a -> String- -> [(String, Parse Attribute)]-parseFieldDef c d fld = [(fld, p)]- where- p = liftEqParse fld c- `onFail`- do nxt <- optional $ satisfy restIDString- bool (fail "Not actually the field you were after")- (return $ c d)- (isNothing nxt)---- | Attempt to parse the @\"=value\"@ part of a @key=value@ pair. If--- there is an equal sign but the @value@ part doesn't parse, throw--- an un-recoverable error.-liftEqParse :: (ParseDot a) => String -> (a -> Attribute) -> Parse Attribute-liftEqParse k c = parseEq- *> ( hasDef (fmap c parse)- `adjustErrBad`- (("Unable to parse key=value with key of " ++ k- ++ "\n\t") ++)- )- where- hasDef p = maybe p (onFail p . (`stringRep` "\"\""))- . defaultAttributeValue $ c undefined---- -------------------------------------------------------------------------------{- | If performing any custom pre-/post-processing on Dot code, you- may wish to utilise some custom 'Attributes'. These are wrappers- around the 'UnknownAttribute' constructor (and thus 'CustomAttribute'- is just an alias for 'Attribute').-- You should ensure that 'validUnknown' is 'True' for any potential- custom attribute name.---}-type CustomAttribute = Attribute---- | Create a custom attribute.-customAttribute :: AttributeName -> Text -> CustomAttribute-customAttribute = UnknownAttribute---- | Determines whether or not this is a custom attribute.-isCustom :: Attribute -> Bool-isCustom UnknownAttribute{} = True-isCustom _ = False--isSpecifiedCustom :: AttributeName -> Attribute -> Bool-isSpecifiedCustom nm (UnknownAttribute nm' _) = nm == nm'-isSpecifiedCustom _ _ = False---- | The value of a custom attribute. Will throw a--- 'GraphvizException' if the provided 'Attribute' isn't a custom--- one.-customValue :: CustomAttribute -> Text-customValue (UnknownAttribute _ v) = v-customValue attr = throw . NotCustomAttr . T.unpack- $ printIt attr---- | The name of a custom attribute. Will throw a--- 'GraphvizException' if the provided 'Attribute' isn't a custom--- one.-customName :: CustomAttribute -> AttributeName-customName (UnknownAttribute nm _) = nm-customName attr = throw . NotCustomAttr . T.unpack- $ printIt attr---- | Returns all custom attributes and the list of non-custom Attributes.-findCustoms :: Attributes -> ([CustomAttribute], Attributes)-findCustoms = partition isCustom---- | Find the (first instance of the) specified custom attribute and--- returns it along with all other Attributes.-findSpecifiedCustom :: AttributeName -> Attributes- -> Maybe (CustomAttribute, Attributes)-findSpecifiedCustom nm attrs- = case break (isSpecifiedCustom nm) attrs of- (bf,cust:aft) -> Just (cust, bf ++ aft)- _ -> Nothing---- | Delete all custom attributes (actually, this will delete all--- 'UnknownAttribute' values; as such it can also be used to remove--- legacy attributes).-deleteCustomAttributes :: Attributes -> Attributes-deleteCustomAttributes = filter (not . isCustom)---- | Removes all instances of the specified custom attribute.-deleteSpecifiedCustom :: AttributeName -> Attributes -> Attributes-deleteSpecifiedCustom nm = filter (not . isSpecifiedCustom nm)---- --------------------------------------------------------------------------------- | The available Graphviz commands. The following directions are--- based upon those in the Graphviz man page (available online at--- <http://graphviz.org/pdf/dot.1.pdf>, or if installed on your--- system @man graphviz@). Note that any command can be used on--- both directed and undirected graphs.------ When used with the 'Layout' attribute, it overrides any actual--- command called on the dot graph.-data GraphvizCommand = Dot -- ^ For hierachical graphs (ideal for- -- directed graphs).- | Neato -- ^ For symmetric layouts of graphs- -- (ideal for undirected graphs).- | TwoPi -- ^ For radial layout of graphs.- | Circo -- ^ For circular layout of graphs.- | Fdp -- ^ Spring-model approach for- -- undirected graphs.- | Sfdp -- ^ As with Fdp, but ideal for large- -- graphs.- | Osage -- ^ Filter for drawing clustered graphs,- -- requires Graphviz >= 2.28.0.- | Patchwork -- ^ Draw clustered graphs as treemaps,- -- requires Graphviz >= 2.28.0.- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot GraphvizCommand where- unqtDot Dot = text "dot"- unqtDot Neato = text "neato"- unqtDot TwoPi = text "twopi"- unqtDot Circo = text "circo"- unqtDot Fdp = text "fdp"- unqtDot Sfdp = text "sfdp"- unqtDot Osage = text "osage"- unqtDot Patchwork = text "patchwork"--instance ParseDot GraphvizCommand where- parseUnqt = stringValue [ ("dot", Dot)- , ("neato", Neato)- , ("twopi", TwoPi)- , ("circo", Circo)- , ("fdp", Fdp)- , ("sfdp", Sfdp)- , ("osage", Osage)- , ("patchwork", Patchwork)- ]---- -------------------------------------------------------------------------------{- |-- Some 'Attribute's (mainly label-like ones) take a 'String' argument- that allows for extra escape codes. This library doesn't do any- extra checks or special parsing for these escape codes, but usage- of 'EscString' rather than 'Text' indicates that the Graphviz- tools will recognise these extra escape codes for these- 'Attribute's.-- The extra escape codes include (note that these are all Strings):-- [@\\N@] Replace with the name of the node (for Node 'Attribute's).-- [@\\G@] Replace with the name of the graph (for Node 'Attribute's)- or the name of the graph or cluster, whichever is- applicable (for Graph, Cluster and Edge 'Attribute's).-- [@\\E@] Replace with the name of the edge, formed by the two- adjoining nodes and the edge type (for Edge 'Attribute's).-- [@\\T@] Replace with the name of the tail node (for Edge- 'Attribute's).-- [@\\H@] Replace with the name of the head node (for Edge- 'Attribute's).-- [@\\L@] Replace with the object's label (for all 'Attribute's).-- Also, if the 'Attribute' in question is 'Label', 'HeadLabel' or- 'TailLabel', then @\\n@, @\\l@ and @\\r@ split the label into lines- centered, left-justified and right-justified respectively.-- -}-type EscString = Text---- --------------------------------------------------------------------------------- | /Dot/ has a basic grammar of arrow shapes which allows usage of--- up to 1,544,761 different shapes from 9 different basic--- 'ArrowShape's. Note that whilst an explicit list is used in the--- definition of 'ArrowType', there must be at least one tuple and a--- maximum of 4 (since that is what is required by Dot). For more--- information, see: <http://graphviz.org/doc/info/arrows.html>------ The 19 basic arrows shown on the overall attributes page have--- been defined below as a convenience. Parsing of the 5--- backward-compatible special cases is also supported.-newtype ArrowType = AType [(ArrowModifier, ArrowShape)]- deriving (Eq, Ord, Show, Read)---- Used for default-normal :: ArrowType-normal = AType [(noMods, Normal)]---- Used for backward-compatible parsing-eDiamond, openArr, halfOpen, emptyArr, invEmpty :: ArrowType--eDiamond = AType [(openMod, Diamond)]-openArr = AType [(noMods, Vee)]-halfOpen = AType [(ArrMod FilledArrow LeftSide, Vee)]-emptyArr = AType [(openMod, Normal)]-invEmpty = AType [ (noMods, Inv)- , (openMod, Normal)]--instance PrintDot ArrowType where- unqtDot (AType mas) = hcat $ mapM appMod mas- where- appMod (m, a) = unqtDot m <> unqtDot a--instance ParseDot ArrowType where- parseUnqt = specialArrowParse- `onFail`- (AType <$> many1 (liftA2 (,) parseUnqt parseUnqt))--specialArrowParse :: Parse ArrowType-specialArrowParse = stringValue [ ("ediamond", eDiamond)- , ("open", openArr)- , ("halfopen", halfOpen)- , ("empty", emptyArr)- , ("invempty", invEmpty)- ]--data ArrowShape = Box- | Crow- | Diamond- | DotArrow- | Inv- | NoArrow- | Normal- | Tee- | Vee- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot ArrowShape where- unqtDot Box = text "box"- unqtDot Crow = text "crow"- unqtDot Diamond = text "diamond"- unqtDot DotArrow = text "dot"- unqtDot Inv = text "inv"- unqtDot NoArrow = text "none"- unqtDot Normal = text "normal"- unqtDot Tee = text "tee"- unqtDot Vee = text "vee"--instance ParseDot ArrowShape where- parseUnqt = stringValue [ ("box", Box)- , ("crow", Crow)- , ("diamond", Diamond)- , ("dot", DotArrow)- , ("inv", Inv)- , ("none", NoArrow)- , ("normal", Normal)- , ("tee", Tee)- , ("vee", Vee)- ]---- | What modifications to apply to an 'ArrowShape'.-data ArrowModifier = ArrMod { arrowFill :: ArrowFill- , arrowSide :: ArrowSide- }- deriving (Eq, Ord, Show, Read)---- | Apply no modifications to an 'ArrowShape'.-noMods :: ArrowModifier-noMods = ArrMod FilledArrow BothSides---- | 'OpenArrow' and 'BothSides'-openMod :: ArrowModifier-openMod = ArrMod OpenArrow BothSides--instance PrintDot ArrowModifier where- unqtDot (ArrMod f s) = unqtDot f <> unqtDot s--instance ParseDot ArrowModifier where- parseUnqt = liftA2 ArrMod parseUnqt parseUnqt--data ArrowFill = OpenArrow- | FilledArrow- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot ArrowFill where- unqtDot OpenArrow = char 'o'- unqtDot FilledArrow = empty--instance ParseDot ArrowFill where- parseUnqt = bool FilledArrow OpenArrow . isJust <$> optional (character 'o')-- -- Not used individually- parse = parseUnqt---- | Represents which side (when looking towards the node the arrow is--- pointing to) is drawn.-data ArrowSide = LeftSide- | RightSide- | BothSides- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot ArrowSide where- unqtDot LeftSide = char 'l'- unqtDot RightSide = char 'r'- unqtDot BothSides = empty--instance ParseDot ArrowSide where- parseUnqt = getSideType <$> optional (oneOf $ map character ['l', 'r'])- where- getSideType = maybe BothSides- (bool RightSide LeftSide . (==) 'l')-- -- Not used individually- parse = parseUnqt---- -------------------------------------------------------------------------------data AspectType = RatioOnly Double- | RatioPassCount Double Int- deriving (Eq, Ord, Show, Read)--instance PrintDot AspectType where- unqtDot (RatioOnly r) = unqtDot r- unqtDot (RatioPassCount r p) = commaDel r p-- toDot at@RatioOnly{} = unqtDot at- toDot at@RatioPassCount{} = dquotes $ unqtDot at--instance ParseDot AspectType where- parseUnqt = fmap (uncurry RatioPassCount) commaSepUnqt- `onFail`- fmap RatioOnly parseUnqt--- parse = quotedParse (uncurry RatioPassCount <$> commaSepUnqt)- `onFail`- fmap RatioOnly parse---- --------------------------------------------------------------------------------- | Should only have 2D points (i.e. created with 'createPoint').-data Rect = Rect Point Point- deriving (Eq, Ord, Show, Read)--instance PrintDot Rect where- unqtDot (Rect p1 p2) = printPoint2DUnqt p1 <> comma <> printPoint2DUnqt p2-- toDot = dquotes . unqtDot-- unqtListToDot = hsep . mapM unqtDot--instance ParseDot Rect where- parseUnqt = uncurry Rect <$> commaSep' parsePoint2D parsePoint2D-- parse = quotedParse parseUnqt-- parseUnqtList = sepBy1 parseUnqt whitespace1---- --------------------------------------------------------------------------------- | If 'Local', then sub-graphs that are clusters are given special--- treatment. 'Global' and 'NoCluster' currently appear to be--- identical and turn off the special cluster processing.-data ClusterMode = Local- | Global- | NoCluster- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot ClusterMode where- unqtDot Local = text "local"- unqtDot Global = text "global"- unqtDot NoCluster = text "none"--instance ParseDot ClusterMode where- parseUnqt = oneOf [ stringRep Local "local"- , stringRep Global "global"- , stringRep NoCluster "none"- ]---- --------------------------------------------------------------------------------- | Specify where to place arrow heads on an edge.-data DirType = Forward -- ^ Draw a directed edge with an arrow to the- -- node it's pointing go.- | Back -- ^ Draw a reverse directed edge with an arrow- -- to the node it's coming from.- | Both -- ^ Draw arrows on both ends of the edge.- | NoDir -- ^ Draw an undirected edge.- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot DirType where- unqtDot Forward = text "forward"- unqtDot Back = text "back"- unqtDot Both = text "both"- unqtDot NoDir = text "none"--instance ParseDot DirType where- parseUnqt = oneOf [ stringRep Forward "forward"- , stringRep Back "back"- , stringRep Both "both"- , stringRep NoDir "none"- ]---- --------------------------------------------------------------------------------- | Only when @mode == 'IpSep'@.-data DEConstraints = EdgeConstraints- | NoConstraints- | HierConstraints- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot DEConstraints where- unqtDot EdgeConstraints = unqtDot True- unqtDot NoConstraints = unqtDot False- unqtDot HierConstraints = text "hier"--instance ParseDot DEConstraints where- parseUnqt = fmap (bool NoConstraints EdgeConstraints) parse- `onFail`- stringRep HierConstraints "hier"---- --------------------------------------------------------------------------------- | Either a 'Double' or a (2D) 'Point' (i.e. created with--- 'createPoint').------ Whilst it is possible to create a 'Point' value with either a--- third co-ordinate or a forced position, these are ignored for--- printing/parsing.------ An optional prefix of @\'+\'@ is allowed when parsing.-data DPoint = DVal Double- | PVal Point- deriving (Eq, Ord, Show, Read)--instance PrintDot DPoint where- unqtDot (DVal d) = unqtDot d- unqtDot (PVal p) = printPoint2DUnqt p-- toDot (DVal d) = toDot d- toDot (PVal p) = printPoint2D p--instance ParseDot DPoint where- parseUnqt = optional (character '+')- *> oneOf [ PVal <$> parsePoint2D- , DVal <$> parseUnqt- ]-- parse = quotedParse parseUnqt -- A `+' would need to be quoted.- `onFail`- fmap DVal parseUnqt---- --------------------------------------------------------------------------------- | The mapping used for 'FontName' values in SVG output.------ More information can be found at <http://www.graphviz.org/doc/fontfaq.txt>.-data SVGFontNames = SvgNames -- ^ Use the legal generic SVG font names.- | PostScriptNames -- ^ Use PostScript font names.- | FontConfigNames -- ^ Use fontconfig font conventions.- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot SVGFontNames where- unqtDot SvgNames = text "svg"- unqtDot PostScriptNames = text "ps"- unqtDot FontConfigNames = text "gd"--instance ParseDot SVGFontNames where- parseUnqt = oneOf [ stringRep SvgNames "svg"- , stringRep PostScriptNames "ps"- , stringRep FontConfigNames "gd"- ]-- parse = stringRep SvgNames "\"\""- `onFail`- optionalQuoted parseUnqt---- --------------------------------------------------------------------------------- | Maximum width and height of drawing in inches.-data GraphSize = GSize { width :: Double- -- | If @Nothing@, then the height is the- -- same as the width.- , height :: Maybe Double- -- | If drawing is smaller than specified- -- size, this value determines whether it- -- is scaled up.- , desiredSize :: Bool- }- deriving (Eq, Ord, Show, Read)--instance PrintDot GraphSize where- unqtDot (GSize w mh ds) = bool id (<> char '!') ds- . maybe id (\h -> (<> unqtDot h) . (<> comma)) mh- $ unqtDot w-- toDot (GSize w Nothing False) = toDot w- toDot gs = dquotes $ unqtDot gs--instance ParseDot GraphSize where- parseUnqt = GSize <$> parseUnqt- <*> optional (parseComma *> whitespace *> parseUnqt)- <*> (isJust <$> optional (character '!'))-- parse = quotedParse parseUnqt- `onFail`- fmap (\ w -> GSize w Nothing False) parseUnqt---- -------------------------------------------------------------------------------data ModeType = Major- | KK- | Hier- | IpSep- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot ModeType where- unqtDot Major = text "major"- unqtDot KK = text "KK"- unqtDot Hier = text "hier"- unqtDot IpSep = text "ipsep"--instance ParseDot ModeType where- parseUnqt = oneOf [ stringRep Major "major"- , stringRep KK "KK"- , stringRep Hier "hier"- , stringRep IpSep "ipsep"- ]---- -------------------------------------------------------------------------------data Model = ShortPath- | SubSet- | Circuit- | MDS- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot Model where- unqtDot ShortPath = text "shortpath"- unqtDot SubSet = text "subset"- unqtDot Circuit = text "circuit"- unqtDot MDS = text "mds"--instance ParseDot Model where- parseUnqt = oneOf [ stringRep ShortPath "shortpath"- , stringRep SubSet "subset"- , stringRep Circuit "circuit"- , stringRep MDS "mds"- ]---- -------------------------------------------------------------------------------data Label = StrLabel EscString- | HtmlLabel Html.Label -- ^ If 'PlainText' is used, the- -- 'Html.Label' value is the entire- -- \"shape\"; if anything else- -- except 'PointShape' is used then- -- the 'Html.Label' is embedded- -- within the shape.- | RecordLabel RecordFields -- ^ For nodes only; requires- -- either 'Record' or- -- 'MRecord' as the shape.- deriving (Eq, Ord, Show, Read)--instance PrintDot Label where- unqtDot (StrLabel s) = unqtDot s- unqtDot (HtmlLabel h) = angled $ unqtDot h- unqtDot (RecordLabel fs) = unqtDot fs-- toDot (StrLabel s) = toDot s- toDot h@HtmlLabel{} = unqtDot h- toDot (RecordLabel fs) = toDot fs--instance ParseDot Label where- -- Don't have to worry about being able to tell the difference- -- between an HtmlLabel and a RecordLabel starting with a PortPos,- -- since the latter will be in quotes and the former won't.-- parseUnqt = oneOf [ HtmlLabel <$> parseAngled parseUnqt- , RecordLabel <$> parseUnqt- , StrLabel <$> parseUnqt- ]-- parse = oneOf [ HtmlLabel <$> parseAngled parse- , RecordLabel <$> parse- , StrLabel <$> parse- ]---- --------------------------------------------------------------------------------- | A RecordFields value should never be empty.-type RecordFields = [RecordField]---- | Specifies the sub-values of a record-based label. By default,--- the cells are laid out horizontally; use 'FlipFields' to change--- the orientation of the fields (can be applied recursively). To--- change the default orientation, use 'RankDir'.-data RecordField = LabelledTarget PortName EscString- | PortName PortName -- ^ Will result in no label for- -- that cell.- | FieldLabel EscString- | FlipFields RecordFields- deriving (Eq, Ord, Show, Read)--instance PrintDot RecordField where- -- Have to use 'printPortName' to add the @\'<\'@ and @\'>\'@.- unqtDot (LabelledTarget t s) = printPortName t <+> unqtRecordString s- unqtDot (PortName t) = printPortName t- unqtDot (FieldLabel s) = unqtRecordString s- unqtDot (FlipFields rs) = braces $ unqtDot rs-- toDot (FieldLabel s) = printEscaped recordEscChars s- toDot rf = dquotes $ unqtDot rf-- unqtListToDot [f] = unqtDot f- unqtListToDot fs = hcat . punctuate (char '|') $ mapM unqtDot fs-- listToDot [f] = toDot f- listToDot fs = dquotes $ unqtListToDot fs--instance ParseDot RecordField where- parseUnqt = (liftA2 maybe PortName LabelledTarget- <$> (PN <$> parseAngled parseRecord)- <*> optional (whitespace1 *> parseRecord)- )- `onFail`- fmap FieldLabel parseRecord- `onFail`- fmap FlipFields (parseBraced parseUnqt)- `onFail`- fail "Unable to parse RecordField"-- parse = quotedParse parseUnqt-- parseUnqtList = wrapWhitespace $ sepBy1 parseUnqt (wrapWhitespace $ character '|')-- -- Note: a singleton unquoted 'FieldLabel' is /not/ valid, as it- -- will cause parsing problems for other 'Label' types.- parseList = do rfs <- quotedParse parseUnqtList- if validRFs rfs- then return rfs- else fail "This is a StrLabel, not a RecordLabel"- where- validRFs [FieldLabel str] = T.any (`elem` recordEscChars) str- validRFs _ = True---- | Print a 'PortName' value as expected within a Record data--- structure.-printPortName :: PortName -> DotCode-printPortName = angled . unqtRecordString . portName--parseRecord :: Parse Text-parseRecord = parseEscaped False recordEscChars []--unqtRecordString :: Text -> DotCode-unqtRecordString = unqtEscaped recordEscChars--recordEscChars :: [Char]-recordEscChars = ['{', '}', '|', ' ', '<', '>']---- --------------------------------------------------------------------------------- | How to treat a node whose name is of the form \"@|edgelabel|*@\"--- as a special node representing an edge label.-data LabelScheme = NotEdgeLabel -- ^ No effect- | CloseToCenter -- ^ Make node close to center of neighbor- | CloseToOldCenter -- ^ Make node close to old center of neighbor- | RemoveAndStraighten -- ^ Use a two-step process.- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot LabelScheme where- unqtDot NotEdgeLabel = int 0- unqtDot CloseToCenter = int 1- unqtDot CloseToOldCenter = int 2- unqtDot RemoveAndStraighten = int 3--instance ParseDot LabelScheme where- -- Use string-based parsing rather than parsing an integer just to make it easier- parseUnqt = stringValue [ ("0", NotEdgeLabel)- , ("1", CloseToCenter)- , ("2", CloseToOldCenter)- , ("3", RemoveAndStraighten)- ]---- -------------------------------------------------------------------------------data Point = Point { xCoord :: Double- , yCoord :: Double- -- | Can only be 'Just' for @'Dim' 3@ or greater.- , zCoord :: Maybe Double- -- | Input to Graphviz only: specify that the- -- node position should not change.- , forcePos :: Bool- }- deriving (Eq, Ord, Show, Read)---- | Create a point with only @x@ and @y@ values.-createPoint :: Double -> Double -> Point-createPoint x y = Point x y Nothing False--printPoint2DUnqt :: Point -> DotCode-printPoint2DUnqt p = commaDel (xCoord p) (yCoord p)--printPoint2D :: Point -> DotCode-printPoint2D = dquotes . printPoint2DUnqt--parsePoint2D :: Parse Point-parsePoint2D = uncurry createPoint <$> commaSepUnqt--instance PrintDot Point where- unqtDot (Point x y mz frs) = bool id (<> char '!') frs- . maybe id (\ z -> (<> unqtDot z) . (<> comma)) mz- $ commaDel x y-- toDot = dquotes . unqtDot-- unqtListToDot = hsep . mapM unqtDot-- listToDot = dquotes . unqtListToDot--instance ParseDot Point where- parseUnqt = uncurry Point- <$> commaSepUnqt- <*> optional (parseComma *> parseUnqt)- <*> (isJust <$> optional (character '!'))-- parse = quotedParse parseUnqt-- parseUnqtList = sepBy1 parseUnqt whitespace1---- --------------------------------------------------------------------------------- | How to deal with node overlaps.------ Defaults to 'KeepOverlaps' /except/ for fdp and sfdp.------ The ability to specify the number of tries for fdp's initial--- force-directed technique is /not/ supported (by default, fdp uses--- @9@ passes of its in-built technique, and then @'PrismOverlap'--- Nothing@).------ For sfdp, the default is @'PrismOverlap' (Just 0)@.-data Overlap = KeepOverlaps- | ScaleOverlaps -- ^ Remove overlaps by uniformly scaling in x and y.- | ScaleXYOverlaps -- ^ Remove overlaps by separately scaling x and y.- | PrismOverlap (Maybe Word16) -- ^ Requires the Prism- -- library to be- -- available (if not,- -- this is equivalent to- -- 'VoronoiOverlap'). @'Nothing'@- -- is equivalent to- -- @'Just' 1000@.- -- Influenced by- -- 'OverlapScaling'.- | VoronoiOverlap -- ^ Requires Graphviz >= 2.30.0.- | CompressOverlap -- ^ Scale layout down as much as- -- possible without introducing- -- overlaps, assuming none to begin- -- with.- | VpscOverlap -- ^ Uses quadratic optimization to- -- minimize node displacement.- | IpsepOverlap -- ^ Only when @mode == 'IpSep'@- deriving (Eq, Ord, Show, Read)--instance PrintDot Overlap where- unqtDot KeepOverlaps = unqtDot True- unqtDot ScaleOverlaps = text "scale"- unqtDot ScaleXYOverlaps = text "scalexy"- unqtDot (PrismOverlap i) = maybe id (flip (<>) . unqtDot) i $ text "prism"- unqtDot VoronoiOverlap = text "voronoi"- unqtDot CompressOverlap = text "compress"- unqtDot VpscOverlap = text "vpsc"- unqtDot IpsepOverlap = text "ipsep"---- | Note that @overlap=false@ defaults to @'PrismOverlap' Nothing@,--- but if the Prism library isn't available then it is equivalent to--- 'VoronoiOverlap'.-instance ParseDot Overlap where- parseUnqt = oneOf [ stringRep KeepOverlaps "true"- , stringRep ScaleXYOverlaps "scalexy"- , stringRep ScaleOverlaps "scale"- , string "prism" *> fmap PrismOverlap (optional parse)- , stringRep (PrismOverlap Nothing) "false"- , stringRep VoronoiOverlap "voronoi"- , stringRep CompressOverlap "compress"- , stringRep VpscOverlap "vpsc"- , stringRep IpsepOverlap "ipsep"- ]---- -------------------------------------------------------------------------------newtype LayerSep = LSep Text- deriving (Eq, Ord, Show, Read)--instance PrintDot LayerSep where- unqtDot (LSep ls) = setLayerSep (T.unpack ls) *> unqtDot ls-- toDot (LSep ls) = setLayerSep (T.unpack ls) *> toDot ls--instance ParseDot LayerSep where- parseUnqt = do ls <- parseUnqt- setLayerSep $ T.unpack ls- return $ LSep ls-- parse = do ls <- parse- setLayerSep $ T.unpack ls- return $ LSep ls--newtype LayerListSep = LLSep Text- deriving (Eq, Ord, Show, Read)--instance PrintDot LayerListSep where- unqtDot (LLSep ls) = setLayerListSep (T.unpack ls) *> unqtDot ls-- toDot (LLSep ls) = setLayerListSep (T.unpack ls) *> toDot ls--instance ParseDot LayerListSep where- parseUnqt = do ls <- parseUnqt- setLayerListSep $ T.unpack ls- return $ LLSep ls-- parse = do ls <- parse- setLayerListSep $ T.unpack ls- return $ LLSep ls--type LayerRange = [LayerRangeElem]--data LayerRangeElem = LRID LayerID- | LRS LayerID LayerID- deriving (Eq, Ord, Show, Read)--instance PrintDot LayerRangeElem where- unqtDot (LRID lid) = unqtDot lid- unqtDot (LRS id1 id2) = do ls <- getLayerSep- let s = unqtDot $ head ls- unqtDot id1 <> s <> unqtDot id2-- toDot (LRID lid) = toDot lid- toDot lrs = dquotes $ unqtDot lrs-- unqtListToDot lr = do lls <- getLayerListSep- let s = unqtDot $ head lls- hcat . punctuate s $ mapM unqtDot lr-- listToDot [lre] = toDot lre- listToDot lrs = dquotes $ unqtListToDot lrs--instance ParseDot LayerRangeElem where- parseUnqt = ignoreSep LRS parseUnqt parseLayerSep parseUnqt- `onFail`- fmap LRID parseUnqt-- parse = quotedParse (ignoreSep LRS parseUnqt parseLayerSep parseUnqt)- `onFail`- fmap LRID parse-- parseUnqtList = sepBy parseUnqt parseLayerListSep-- parseList = quotedParse parseUnqtList- `onFail`- fmap ((:[]) . LRID) parse--parseLayerSep :: Parse ()-parseLayerSep = do ls <- getLayerSep- many1Satisfy (`elem` ls) *> return ()--parseLayerName :: Parse Text-parseLayerName = parseEscaped False [] =<< liftA2 (++) getLayerSep getLayerListSep--parseLayerName' :: Parse Text-parseLayerName' = stringBlock- `onFail`- quotedParse parseLayerName--parseLayerListSep :: Parse ()-parseLayerListSep = do lls <- getLayerListSep- many1Satisfy (`elem` lls) *> return ()---- | You should not have any layer separator characters for the--- 'LRName' option, as they won't be parseable.-data LayerID = AllLayers- | LRInt Int- | LRName Text -- ^ Should not be a number or @"all"@.- deriving (Eq, Ord, Show, Read)--instance PrintDot LayerID where- unqtDot AllLayers = text "all"- unqtDot (LRInt n) = unqtDot n- unqtDot (LRName nm) = unqtDot nm-- toDot (LRName nm) = toDot nm- -- Other two don't need quotes- toDot li = unqtDot li-- unqtListToDot ll = do ls <- getLayerSep- let s = unqtDot $ head ls- hcat . punctuate s $ mapM unqtDot ll-- listToDot [l] = toDot l- -- Might not need quotes, but probably will. Can't tell either- -- way since we don't know what the separator character will be.- listToDot ll = dquotes $ unqtDot ll--instance ParseDot LayerID where- parseUnqt = checkLayerName <$> parseLayerName -- tests for Int and All-- parse = oneOf [ checkLayerName <$> parseLayerName'- , LRInt <$> parse -- Mainly for unquoted case.- ]--checkLayerName :: Text -> LayerID-checkLayerName str = maybe checkAll LRInt $ stringToInt str- where- checkAll = if T.toLower str == "all"- then AllLayers- else LRName str---- Remember: this /must/ be a newtype as we can't use arbitrary--- LayerID values!---- | A list of layer names. The names should all be unique 'LRName'--- values, and when printed will use an arbitrary character from--- 'defLayerSep'. The values in the list are implicitly numbered--- @1, 2, ...@.-newtype LayerList = LL [LayerID]- deriving (Eq, Ord, Show, Read)--instance PrintDot LayerList where- unqtDot (LL ll) = unqtDot ll-- toDot (LL ll) = toDot ll--instance ParseDot LayerList where- parseUnqt = LL <$> sepBy1 parseUnqt parseLayerSep-- parse = quotedParse parseUnqt- `onFail`- fmap (LL . (:[]) . LRName) stringBlock- `onFail`- quotedParse (stringRep (LL []) "")---- -------------------------------------------------------------------------------data Order = OutEdges -- ^ Draw outgoing edges in order specified.- | InEdges -- ^ Draw incoming edges in order specified.- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot Order where- unqtDot OutEdges = text "out"- unqtDot InEdges = text "in"--instance ParseDot Order where- parseUnqt = oneOf [ stringRep OutEdges "out"- , stringRep InEdges "in"- ]---- -------------------------------------------------------------------------------data OutputMode = BreadthFirst | NodesFirst | EdgesFirst- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot OutputMode where- unqtDot BreadthFirst = text "breadthfirst"- unqtDot NodesFirst = text "nodesfirst"- unqtDot EdgesFirst = text "edgesfirst"--instance ParseDot OutputMode where- parseUnqt = oneOf [ stringRep BreadthFirst "breadthfirst"- , stringRep NodesFirst "nodesfirst"- , stringRep EdgesFirst "edgesfirst"- ]---- -------------------------------------------------------------------------------data Pack = DoPack- | DontPack- | PackMargin Int -- ^ If non-negative, then packs; otherwise doesn't.- deriving (Eq, Ord, Show, Read)--instance PrintDot Pack where- unqtDot DoPack = unqtDot True- unqtDot DontPack = unqtDot False- unqtDot (PackMargin m) = unqtDot m--instance ParseDot Pack where- -- What happens if it parses 0? It's non-negative, but parses as False- parseUnqt = oneOf [ PackMargin <$> parseUnqt- , bool DontPack DoPack <$> onlyBool- ]---- -------------------------------------------------------------------------------data PackMode = PackNode- | PackClust- | PackGraph- | PackArray Bool Bool (Maybe Int) -- ^ Sort by cols, sort- -- by user, number of- -- rows/cols- deriving (Eq, Ord, Show, Read)--instance PrintDot PackMode where- unqtDot PackNode = text "node"- unqtDot PackClust = text "clust"- unqtDot PackGraph = text "graph"- unqtDot (PackArray c u mi) = addNum . isU . isC . isUnder- $ text "array"- where- addNum = maybe id (flip (<>) . unqtDot) mi- isUnder = if c || u- then (<> char '_')- else id- isC = if c- then (<> char 'c')- else id- isU = if u- then (<> char 'u')- else id--instance ParseDot PackMode where- parseUnqt = oneOf [ stringRep PackNode "node"- , stringRep PackClust "clust"- , stringRep PackGraph "graph"- , do string "array"- mcu <- optional $ character '_' *> many1 (satisfy isCU)- let c = hasCharacter mcu 'c'- u = hasCharacter mcu 'u'- mi <- optional parseUnqt- return $ PackArray c u mi- ]- where- hasCharacter ms c = maybe False (elem c) ms- -- Also checks and removes quote characters- isCU = (`elem` ['c', 'u'])---- -------------------------------------------------------------------------------data Pos = PointPos Point- | SplinePos [Spline]- deriving (Eq, Ord, Show, Read)--instance PrintDot Pos where- unqtDot (PointPos p) = unqtDot p- unqtDot (SplinePos ss) = unqtDot ss-- toDot (PointPos p) = toDot p- toDot (SplinePos ss) = toDot ss--instance ParseDot Pos where- -- Have to be careful with this: if we try to parse points first,- -- then a spline with no start and end points will erroneously get- -- parsed as a point and then the parser will crash as it expects a- -- closing quote character...- parseUnqt = do splns <- parseUnqt- case splns of- [Spline Nothing Nothing [p]] -> return $ PointPos p- _ -> return $ SplinePos splns-- parse = quotedParse parseUnqt---- --------------------------------------------------------------------------------- | Controls how (and if) edges are represented.------ For @dot@, the default is 'SplineEdges'; for all other layouts--- the default is 'LineEdges'.-data EdgeType = SplineEdges -- ^ Except for dot, requires- -- non-overlapping nodes (see- -- 'Overlap').- | LineEdges- | NoEdges- | PolyLine- | Ortho -- ^ Does not handle ports or edge labels in dot.- | Curved -- ^ Requires Graphviz >= 2.30.0.- | CompoundEdge -- ^ fdp only- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot EdgeType where- unqtDot SplineEdges = text "spline"- unqtDot LineEdges = text "line"- unqtDot NoEdges = empty- unqtDot PolyLine = text "polyline"- unqtDot Ortho = text "ortho"- unqtDot Curved = text "curved"- unqtDot CompoundEdge = text "compound"-- toDot NoEdges = dquotes empty- toDot et = unqtDot et--instance ParseDot EdgeType where- -- Can't parse NoEdges without quotes.- parseUnqt = oneOf [ bool LineEdges SplineEdges <$> parse- , stringRep SplineEdges "spline"- , stringRep LineEdges "line"- , stringRep NoEdges "none"- , stringRep PolyLine "polyline"- , stringRep Ortho "ortho"- , stringRep Curved "curved"- , stringRep CompoundEdge "compound"- ]-- parse = stringRep NoEdges "\"\""- `onFail`- optionalQuoted parseUnqt---- --------------------------------------------------------------------------------- | Upper-case first character is major order;--- lower-case second character is minor order.-data PageDir = Bl | Br | Tl | Tr | Rb | Rt | Lb | Lt- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot PageDir where- unqtDot Bl = text "BL"- unqtDot Br = text "BR"- unqtDot Tl = text "TL"- unqtDot Tr = text "TR"- unqtDot Rb = text "RB"- unqtDot Rt = text "RT"- unqtDot Lb = text "LB"- unqtDot Lt = text "LT"--instance ParseDot PageDir where- parseUnqt = stringValue [ ("BL", Bl)- , ("BR", Br)- , ("TL", Tl)- , ("TR", Tr)- , ("RB", Rb)- , ("RT", Rt)- , ("LB", Lb)- , ("LT", Lt)- ]---- --------------------------------------------------------------------------------- | The number of points in the list must be equivalent to 1 mod 3;--- note that this is not checked.-data Spline = Spline { endPoint :: Maybe Point- , startPoint :: Maybe Point- , splinePoints :: [Point]- }- deriving (Eq, Ord, Show, Read)--instance PrintDot Spline where- unqtDot (Spline me ms ps) = addE . addS- . hsep- $ mapM unqtDot ps- where- addP t = maybe id ((<+>) . commaDel t)- addS = addP 's' ms- addE = addP 'e' me-- toDot = dquotes . unqtDot-- unqtListToDot = hcat . punctuate semi . mapM unqtDot-- listToDot = dquotes . unqtListToDot--instance ParseDot Spline where- parseUnqt = Spline <$> parseP 'e' <*> parseP 's'- <*> sepBy1 parseUnqt whitespace1- where- parseP t = optional (character t *> parseComma *> parseUnqt <* whitespace1)-- parse = quotedParse parseUnqt-- parseUnqtList = sepBy1 parseUnqt (character ';')---- -------------------------------------------------------------------------------data QuadType = NormalQT- | FastQT- | NoQT- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot QuadType where- unqtDot NormalQT = text "normal"- unqtDot FastQT = text "fast"- unqtDot NoQT = text "none"--instance ParseDot QuadType where- -- Have to take into account the slightly different interpretation- -- of Bool used as an option for parsing QuadType- parseUnqt = oneOf [ stringRep NormalQT "normal"- , stringRep FastQT "fast"- , stringRep NoQT "none"- , character '2' *> return FastQT -- weird bool- , bool NoQT NormalQT <$> parse- ]---- --------------------------------------------------------------------------------- | Specify the root node either as a Node attribute or a Graph attribute.-data Root = IsCentral -- ^ For Nodes only- | NotCentral -- ^ For Nodes only- | NodeName Text -- ^ For Graphs only- deriving (Eq, Ord, Show, Read)--instance PrintDot Root where- unqtDot IsCentral = unqtDot True- unqtDot NotCentral = unqtDot False- unqtDot (NodeName n) = unqtDot n-- toDot (NodeName n) = toDot n- toDot r = unqtDot r--instance ParseDot Root where- parseUnqt = fmap (bool NotCentral IsCentral) onlyBool- `onFail`- fmap NodeName parseUnqt-- parse = optionalQuoted (bool NotCentral IsCentral <$> onlyBool)- `onFail`- fmap NodeName parse---- -------------------------------------------------------------------------------data RankType = SameRank- | MinRank- | SourceRank- | MaxRank- | SinkRank- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot RankType where- unqtDot SameRank = text "same"- unqtDot MinRank = text "min"- unqtDot SourceRank = text "source"- unqtDot MaxRank = text "max"- unqtDot SinkRank = text "sink"--instance ParseDot RankType where- parseUnqt = stringValue [ ("same", SameRank)- , ("min", MinRank)- , ("source", SourceRank)- , ("max", MaxRank)- , ("sink", SinkRank)- ]---- -------------------------------------------------------------------------------data RankDir = FromTop- | FromLeft- | FromBottom- | FromRight- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot RankDir where- unqtDot FromTop = text "TB"- unqtDot FromLeft = text "LR"- unqtDot FromBottom = text "BT"- unqtDot FromRight = text "RL"--instance ParseDot RankDir where- parseUnqt = oneOf [ stringRep FromTop "TB"- , stringRep FromLeft "LR"- , stringRep FromBottom "BT"- , stringRep FromRight "RL"- ]---- --------------------------------------------------------------------------------- | Geometries of shapes are affected by the attributes 'Regular',--- 'Peripheries' and 'Orientation'.-data Shape- = BoxShape -- ^ Has synonyms of /rect/ and /rectangle/.- | Polygon -- ^ Also affected by 'Sides', 'Skew' and 'Distortion'.- | Ellipse -- ^ Has synonym of /oval/.- | Circle- | PointShape -- ^ Only affected by 'Peripheries', 'Width' and- -- 'Height'.- | Egg- | Triangle- | PlainText -- ^ Has synonym of /none/. Recommended for- -- 'HtmlLabel's.- | DiamondShape- | Trapezium- | Parallelogram- | House- | Pentagon- | Hexagon- | Septagon- | Octagon- | DoubleCircle- | DoubleOctagon- | TripleOctagon- | InvTriangle- | InvTrapezium- | InvHouse- | MDiamond- | MSquare- | MCircle- | Note- | Tab- | Folder- | Box3D- | Component- | Promoter- | CDS- | Terminator- | UTR- | PrimerSite- | RestrictionSite- | FivePovOverhang- | ThreePovOverhang- | NoOverhang- | Assembly- | Signature- | Insulator- | Ribosite- | RNAStab- | ProteaseSite- | ProteinStab- | RPromoter- | RArrow- | LArrow- | LPromoter- | Record -- ^ Must specify the record shape with a 'Label'.- | MRecord -- ^ Must specify the record shape with a 'Label'.- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot Shape where- unqtDot BoxShape = text "box"- unqtDot Polygon = text "polygon"- unqtDot Ellipse = text "ellipse"- unqtDot Circle = text "circle"- unqtDot PointShape = text "point"- unqtDot Egg = text "egg"- unqtDot Triangle = text "triangle"- unqtDot PlainText = text "plaintext"- unqtDot DiamondShape = text "diamond"- unqtDot Trapezium = text "trapezium"- unqtDot Parallelogram = text "parallelogram"- unqtDot House = text "house"- unqtDot Pentagon = text "pentagon"- unqtDot Hexagon = text "hexagon"- unqtDot Septagon = text "septagon"- unqtDot Octagon = text "octagon"- unqtDot DoubleCircle = text "doublecircle"- unqtDot DoubleOctagon = text "doubleoctagon"- unqtDot TripleOctagon = text "tripleoctagon"- unqtDot InvTriangle = text "invtriangle"- unqtDot InvTrapezium = text "invtrapezium"- unqtDot InvHouse = text "invhouse"- unqtDot MDiamond = text "Mdiamond"- unqtDot MSquare = text "Msquare"- unqtDot MCircle = text "Mcircle"- unqtDot Note = text "note"- unqtDot Tab = text "tab"- unqtDot Folder = text "folder"- unqtDot Box3D = text "box3d"- unqtDot Component = text "component"- unqtDot Promoter = text "promoter"- unqtDot CDS = text "cds"- unqtDot Terminator = text "terminator"- unqtDot UTR = text "utr"- unqtDot PrimerSite = text "primersite"- unqtDot RestrictionSite = text "restrictionsite"- unqtDot FivePovOverhang = text "fivepovoverhang"- unqtDot ThreePovOverhang = text "threepovoverhang"- unqtDot NoOverhang = text "nooverhang"- unqtDot Assembly = text "assembly"- unqtDot Signature = text "signature"- unqtDot Insulator = text "insulator"- unqtDot Ribosite = text "ribosite"- unqtDot RNAStab = text "rnastab"- unqtDot ProteaseSite = text "proteasesite"- unqtDot ProteinStab = text "proteinstab"- unqtDot RPromoter = text "rpromoter"- unqtDot RArrow = text "rarrow"- unqtDot LArrow = text "larrow"- unqtDot LPromoter = text "lpromoter"- unqtDot Record = text "record"- unqtDot MRecord = text "Mrecord"--instance ParseDot Shape where- parseUnqt = stringValue [ ("box3d", Box3D)- , ("box", BoxShape)- , ("rectangle", BoxShape)- , ("rect", BoxShape)- , ("polygon", Polygon)- , ("ellipse", Ellipse)- , ("oval", Ellipse)- , ("circle", Circle)- , ("point", PointShape)- , ("egg", Egg)- , ("triangle", Triangle)- , ("plaintext", PlainText)- , ("none", PlainText)- , ("diamond", DiamondShape)- , ("trapezium", Trapezium)- , ("parallelogram", Parallelogram)- , ("house", House)- , ("pentagon", Pentagon)- , ("hexagon", Hexagon)- , ("septagon", Septagon)- , ("octagon", Octagon)- , ("doublecircle", DoubleCircle)- , ("doubleoctagon", DoubleOctagon)- , ("tripleoctagon", TripleOctagon)- , ("invtriangle", InvTriangle)- , ("invtrapezium", InvTrapezium)- , ("invhouse", InvHouse)- , ("Mdiamond", MDiamond)- , ("Msquare", MSquare)- , ("Mcircle", MCircle)- , ("note", Note)- , ("tab", Tab)- , ("folder", Folder)- , ("component", Component)- , ("promoter", Promoter)- , ("cds", CDS)- , ("terminator", Terminator)- , ("utr", UTR)- , ("primersite", PrimerSite)- , ("restrictionsite", RestrictionSite)- , ("fivepovoverhang", FivePovOverhang)- , ("threepovoverhang", ThreePovOverhang)- , ("nooverhang", NoOverhang)- , ("assembly", Assembly)- , ("signature", Signature)- , ("insulator", Insulator)- , ("ribosite", Ribosite)- , ("rnastab", RNAStab)- , ("proteasesite", ProteaseSite)- , ("proteinstab", ProteinStab)- , ("rpromoter", RPromoter)- , ("rarrow", RArrow)- , ("larrow", LArrow)- , ("lpromoter", LPromoter)- , ("record", Record)- , ("Mrecord", MRecord)- ]---- -------------------------------------------------------------------------------data SmoothType = NoSmooth- | AvgDist- | GraphDist- | PowerDist- | RNG- | Spring- | TriangleSmooth- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot SmoothType where- unqtDot NoSmooth = text "none"- unqtDot AvgDist = text "avg_dist"- unqtDot GraphDist = text "graph_dist"- unqtDot PowerDist = text "power_dist"- unqtDot RNG = text "rng"- unqtDot Spring = text "spring"- unqtDot TriangleSmooth = text "triangle"--instance ParseDot SmoothType where- parseUnqt = oneOf [ stringRep NoSmooth "none"- , stringRep AvgDist "avg_dist"- , stringRep GraphDist "graph_dist"- , stringRep PowerDist "power_dist"- , stringRep RNG "rng"- , stringRep Spring "spring"- , stringRep TriangleSmooth "triangle"- ]---- -------------------------------------------------------------------------------data StartType = StartStyle STStyle- | StartSeed Int- | StartStyleSeed STStyle Int- deriving (Eq, Ord, Show, Read)--instance PrintDot StartType where- unqtDot (StartStyle ss) = unqtDot ss- unqtDot (StartSeed s) = unqtDot s- unqtDot (StartStyleSeed ss s) = unqtDot ss <> unqtDot s--instance ParseDot StartType where- parseUnqt = oneOf [ liftA2 StartStyleSeed parseUnqt parseUnqt- , StartStyle <$> parseUnqt- , StartSeed <$> parseUnqt- ]--data STStyle = RegularStyle- | SelfStyle- | RandomStyle- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot STStyle where- unqtDot RegularStyle = text "regular"- unqtDot SelfStyle = text "self"- unqtDot RandomStyle = text "random"--instance ParseDot STStyle where- parseUnqt = oneOf [ stringRep RegularStyle "regular"- , stringRep SelfStyle "self"- , stringRep RandomStyle "random"- ]---- --------------------------------------------------------------------------------- | An individual style item. Except for 'DD', the @['String']@--- should be empty.-data StyleItem = SItem StyleName [Text]- deriving (Eq, Ord, Show, Read)--instance PrintDot StyleItem where- unqtDot (SItem nm args)- | null args = dnm- | otherwise = dnm <> parens args'- where- dnm = unqtDot nm- args' = hcat . punctuate comma $ mapM unqtDot args-- toDot si@(SItem nm args)- | null args = toDot nm- | otherwise = dquotes $ unqtDot si-- unqtListToDot = hcat . punctuate comma . mapM unqtDot-- listToDot [SItem nm []] = toDot nm- listToDot sis = dquotes $ unqtListToDot sis--instance ParseDot StyleItem where- parseUnqt = liftA2 SItem parseUnqt (tryParseList' parseArgs)-- parse = quotedParse (liftA2 SItem parseUnqt parseArgs)- `onFail`- fmap (`SItem` []) parse-- parseUnqtList = sepBy1 parseUnqt parseComma-- parseList = quotedParse parseUnqtList- `onFail`- -- Might not necessarily need to be quoted if a singleton...- fmap return parse--parseArgs :: Parse [Text]-parseArgs = bracketSep (character '(')- parseComma- (character ')')- parseStyleName--data StyleName = Dashed -- ^ Nodes and Edges- | Dotted -- ^ Nodes and Edges- | Solid -- ^ Nodes and Edges- | Bold -- ^ Nodes and Edges- | Invisible -- ^ Nodes and Edges- | Filled -- ^ Nodes and Clusters- | Striped -- ^ Rectangularly-shaped Nodes and- -- Clusters; requires Graphviz >= 2.30.0- | Wedged -- ^ Elliptically-shaped Nodes only;- -- requires Graphviz >= 2.30.0- | Diagonals -- ^ Nodes only- | Rounded -- ^ Nodes and Clusters- | Tapered -- ^ Edges only; requires Graphviz >=- -- 2.29.0- | Radial -- ^ Nodes, Clusters and Graphs, for use- -- with 'GradientAngle'; requires- -- Graphviz >= 2.29.0- | DD Text -- ^ Device Dependent- deriving (Eq, Ord, Show, Read)--instance PrintDot StyleName where- unqtDot Dashed = text "dashed"- unqtDot Dotted = text "dotted"- unqtDot Solid = text "solid"- unqtDot Bold = text "bold"- unqtDot Invisible = text "invis"- unqtDot Filled = text "filled"- unqtDot Striped = text "striped"- unqtDot Wedged = text "wedged"- unqtDot Diagonals = text "diagonals"- unqtDot Rounded = text "rounded"- unqtDot Tapered = text "tapered"- unqtDot Radial = text "radial"- unqtDot (DD nm) = unqtDot nm-- toDot (DD nm) = toDot nm- toDot sn = unqtDot sn--instance ParseDot StyleName where- parseUnqt = checkDD <$> parseStyleName-- parse = quotedParse parseUnqt- `onFail`- fmap checkDD quotelessString--checkDD :: Text -> StyleName-checkDD str = case T.toLower str of- "dashed" -> Dashed- "dotted" -> Dotted- "solid" -> Solid- "bold" -> Bold- "invis" -> Invisible- "filled" -> Filled- "striped" -> Striped- "wedged" -> Wedged- "diagonals" -> Diagonals- "rounded" -> Rounded- "tapered" -> Tapered- "radial" -> Radial- _ -> DD str--parseStyleName :: Parse Text-parseStyleName = liftA2 T.cons (orEscaped . noneOf $ ' ' : disallowedChars)- (parseEscaped True [] disallowedChars)- where- disallowedChars = [quoteChar, '(', ')', ',']- -- Used because the first character has slightly stricter requirements than the rest.- orSlash p = stringRep '\\' "\\\\" `onFail` p- orEscaped = orQuote . orSlash---- -------------------------------------------------------------------------------data ViewPort = VP { wVal :: Double- , hVal :: Double- , zVal :: Double- , focus :: Maybe FocusType- }- deriving (Eq, Ord, Show, Read)--instance PrintDot ViewPort where- unqtDot vp = maybe vs ((<>) (vs <> comma) . unqtDot)- $ focus vp- where- vs = hcat . punctuate comma- $ mapM (unqtDot . ($vp)) [wVal, hVal, zVal]-- toDot = dquotes . unqtDot--instance ParseDot ViewPort where- parseUnqt = VP <$> parseUnqt- <* parseComma- <*> parseUnqt- <* parseComma- <*> parseUnqt- <*> optional (parseComma *> parseUnqt)-- parse = quotedParse parseUnqt---- | For use with 'ViewPort'.-data FocusType = XY Point- | NodeFocus Text- deriving (Eq, Ord, Show, Read)--instance PrintDot FocusType where- unqtDot (XY p) = unqtDot p- unqtDot (NodeFocus nm) = unqtDot nm-- toDot (XY p) = toDot p- toDot (NodeFocus nm) = toDot nm--instance ParseDot FocusType where- parseUnqt = fmap XY parseUnqt- `onFail`- fmap NodeFocus parseUnqt-- parse = fmap XY parse- `onFail`- fmap NodeFocus parse---- -------------------------------------------------------------------------------data VerticalPlacement = VTop- | VCenter -- ^ Only valid for Nodes.- | VBottom- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot VerticalPlacement where- unqtDot VTop = char 't'- unqtDot VCenter = char 'c'- unqtDot VBottom = char 'b'--instance ParseDot VerticalPlacement where- parseUnqt = oneOf [ stringRep VTop "t"- , stringRep VCenter "c"- , stringRep VBottom "b"- ]---- --------------------------------------------------------------------------------- | A list of search paths.-newtype Paths = Paths { paths :: [FilePath] }- deriving (Eq, Ord, Show, Read)--instance PrintDot Paths where- unqtDot = unqtDot . intercalate [searchPathSeparator] . paths-- toDot (Paths [p]) = toDot p- toDot ps = dquotes $ unqtDot ps--instance ParseDot Paths where- parseUnqt = Paths . splitSearchPath <$> parseUnqt-- parse = quotedParse parseUnqt- `onFail`- fmap (Paths . (:[]) . T.unpack) quotelessString---- -------------------------------------------------------------------------------data ScaleType = UniformScale- | NoScale- | FillWidth- | FillHeight- | FillBoth- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot ScaleType where- unqtDot UniformScale = unqtDot True- unqtDot NoScale = unqtDot False- unqtDot FillWidth = text "width"- unqtDot FillHeight = text "height"- unqtDot FillBoth = text "both"--instance ParseDot ScaleType where- parseUnqt = oneOf [ stringRep UniformScale "true"- , stringRep NoScale "false"- , stringRep FillWidth "width"- , stringRep FillHeight "height"- , stringRep FillBoth "both"- ]---- -------------------------------------------------------------------------------data Justification = JLeft- | JRight- | JCenter- deriving (Eq, Ord, Bounded, Enum, Show, Read)--instance PrintDot Justification where- unqtDot JLeft = char 'l'- unqtDot JRight = char 'r'- unqtDot JCenter = char 'c'--instance ParseDot Justification where- parseUnqt = oneOf [ stringRep JLeft "l"- , stringRep JRight "r"- , stringRep JCenter "c"- ]---- -------------------------------------------------------------------------------data Ratios = AspectRatio Double- | FillRatio- | CompressRatio- | ExpandRatio- | AutoRatio- deriving (Eq, Ord, Show, Read)--instance PrintDot Ratios where- unqtDot (AspectRatio r) = unqtDot r- unqtDot FillRatio = text "fill"- unqtDot CompressRatio = text "compress"- unqtDot ExpandRatio = text "expand"- unqtDot AutoRatio = text "auto"--instance ParseDot Ratios where- parseUnqt = oneOf [ AspectRatio <$> parseUnqt- , stringRep FillRatio "fill"- , stringRep CompressRatio "compress"- , stringRep ExpandRatio "expand"- , stringRep AutoRatio "auto"- ]+ * 'Rect' uses two 'Point' values to denote the lower-left and+ top-right corners.++ * The two 'LabelLoc' attributes have been combined.++ * @SplineType@ has been replaced with @['Spline']@.++ * Only polygon-based 'Shape's are available.++ * Not every 'Attribute' is fully documented/described. However,+ all those which have specific allowed values should be covered.++ * Deprecated 'Overlap' algorithms are not defined. Furthermore,+ the ability to specify an integer prefix for use with the fdp layout+ is /not/ supported.++ * The global @Orientation@ attribute is not defined, as it is+ difficult to distinguish from the node-based 'Orientation'+ 'Attribute'; also, its behaviour is duplicated by 'Rotate'.++ * The @charset@ attribute is not available, as graphviz only+ supports UTF-8 encoding (as it is not currently feasible nor needed to+ also support Latin1 encoding).++ * In Graphviz, when a node or edge has a list of attributes, the+ colorscheme which is used to identify a color can be set /after/+ that color (e.g. @[colorscheme=x11,color=grey,colorscheme=svg]@+ uses the svg colorscheme's definition of grey, which is different+ from the x11 one. Instead, graphviz parses them in order.++ -}+module Data.GraphViz.Attributes.Complete+ ( -- * The actual /Dot/ attributes.+ -- $attributes+ Attribute(..)+ , Attributes+ , sameAttribute+ , defaultAttributeValue+ , rmUnwantedAttributes+ -- ** Validity functions on @Attribute@ values.+ , usedByGraphs+ , usedBySubGraphs+ , usedByClusters+ , usedByNodes+ , usedByEdges+ , validUnknown++ -- ** Custom attributes.+ , AttributeName+ , CustomAttribute+ , customAttribute+ , isCustom+ , isSpecifiedCustom+ , customValue+ , customName+ , findCustoms+ , findSpecifiedCustom+ , deleteCustomAttributes+ , deleteSpecifiedCustom++ -- * Value types for @Attribute@s.+ , module Data.GraphViz.Attributes.Colors++ -- ** Generic types+ , Number (..)++ -- ** Labels+ , EscString+ , Label(..)+ , VerticalPlacement(..)+ , LabelScheme(..)+ , SVGFontNames(..)+ -- *** Types representing the Dot grammar for records.+ , RecordFields+ , RecordField(..)+ , Rect(..)+ , Justification(..)++ -- ** Nodes+ , Shape(..)+ , Paths(..)+ , ScaleType(..)+ , NodeSize(..)++ -- ** Edges+ , DirType(..)+ , EdgeType(..)+ -- *** Modifying where edges point+ , PortName(..)+ , PortPos(..)+ , CompassPoint(..)+ -- *** Arrows+ , ArrowType(..)+ , ArrowShape(..)+ , ArrowModifier(..)+ , ArrowFill(..)+ , ArrowSide(..)+ -- **** @ArrowModifier@ values+ , noMods+ , openMod++ -- ** Positioning+ , Point(..)+ , createPoint+ , Pos(..)+ , Spline(..)+ , DPoint(..)+ , Normalized (..)++ -- ** Layout+ , GraphvizCommand(..)+ , GraphSize(..)+ , ClusterMode(..)+ , Model(..)+ , Overlap(..)+ , Root(..)+ , Order(..)+ , OutputMode(..)+ , Pack(..)+ , PackMode(..)+ , PageDir(..)+ , QuadType(..)+ , RankType(..)+ , RankDir(..)+ , StartType(..)+ , ViewPort(..)+ , FocusType(..)+ , Ratios(..)++ -- ** Modes+ , ModeType(..)+ , DEConstraints(..)++ -- ** Layers+ , LayerSep(..)+ , LayerListSep(..)+ , LayerRange+ , LayerRangeElem(..)+ , LayerID(..)+ , LayerList(..)++ -- ** Stylistic+ , SmoothType(..)+ , STStyle(..)+ , StyleItem(..)+ , StyleName(..)+ ) where++import Data.GraphViz.Attributes.Arrows+import Data.GraphViz.Attributes.Colors+import Data.GraphViz.Attributes.Colors.X11 (X11Color (Black))+import Data.GraphViz.Attributes.Internal+import Data.GraphViz.Attributes.Values+import Data.GraphViz.Commands.Available+import Data.GraphViz.Exception (GraphvizException (NotCustomAttr),+ throw)+import Data.GraphViz.Internal.State (getsGS, parseStrictly)+import Data.GraphViz.Internal.Util (bool, isIDString, keywords,+ restIDString)+import Data.GraphViz.Parsing+import Data.GraphViz.Printing++import Data.List (partition)+import Data.Maybe (isNothing)+import qualified Data.Set as S+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Data.Version (Version (..))+import Data.Word (Word16)++-- -----------------------------------------------------------------------------++{- $attributes++ These attributes have been implemented in a /permissive/ manner:+ that is, rather than split them up based on which type of value+ they are allowed, they have all been included in the one data type,+ with functions to determine if they are indeed valid for what+ they're being applied to.++ To interpret the /Valid for/ listings:++ [@G@] Valid for Graphs.++ [@C@] Valid for Clusters.++ [@S@] Valid for Sub-Graphs (and also Clusters).++ [@N@] Valid for Nodes.++ [@E@] Valid for Edges.++ The /Default/ listings are those that the various Graphviz commands+ use if that 'Attribute' isn't specified (in cases where this is+ /none/, this is equivalent to a 'Nothing' value; that is, no value+ is used). The /Parsing Default/ listings represent what value is+ used (i.e. corresponds to 'True') when the 'Attribute' name is+ listed on its own in /Dot/ source code.++ Please note that the 'UnknownAttribute' 'Attribute' is defined+ primarily for backwards-compatibility purposes. It is possible to use+ it directly for custom purposes; for more information, please see+ 'CustomAttribute'. The 'deleteCustomAttributes' can be used to delete+ these values.++ -}++-- | Attributes are used to customise the layout and design of Dot+-- graphs. Care must be taken to ensure that the attribute you use+-- is valid, as not all attributes can be used everywhere.+data Attribute+ = Damping Double -- ^ /Valid for/: G; /Default/: @0.99@; /Minimum/: @0.0@; /Notes/: 'Neato' only+ | K Double -- ^ /Valid for/: GC; /Default/: @0.3@; /Minimum/: @0@; /Notes/: 'Sfdp', 'Fdp' only+ | URL EscString -- ^ /Valid for/: ENGC; /Default/: none; /Notes/: svg, postscript, map only+ | Area Double -- ^ /Valid for/: NC; /Default/: @1.0@; /Minimum/: @>0@; /Notes/: 'Patchwork' only, requires Graphviz >= 2.30.0+ | ArrowHead ArrowType -- ^ /Valid for/: E; /Default/: @'normal'@+ | ArrowSize Double -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0.0@+ | ArrowTail ArrowType -- ^ /Valid for/: E; /Default/: @'normal'@+ | Background Text -- ^ /Valid for/: G; /Default/: none; /Notes/: xdot only+ | BoundingBox Rect -- ^ /Valid for/: G; /Notes/: write only+ | BgColor ColorList -- ^ /Valid for/: GC; /Default/: @[]@+ | Center Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'+ | ClusterRank ClusterMode -- ^ /Valid for/: G; /Default/: @'Local'@; /Notes/: 'Dot' only+ | Color ColorList -- ^ /Valid for/: ENC; /Default/: @['WC' ('X11Color' 'Black') Nothing]@+ | ColorScheme ColorScheme -- ^ /Valid for/: ENCG; /Default/: @'X11'@+ | Comment Text -- ^ /Valid for/: ENG; /Default/: @\"\"@+ | Compound Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: 'Dot' only+ | Concentrate Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'+ | Constraint Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: 'Dot' only+ | Decorate Bool -- ^ /Valid for/: E; /Default/: @'False'@; /Parsing Default/: 'True'+ | DefaultDist Double -- ^ /Valid for/: G; /Default/: @1+(avg. len)*sqrt(abs(V))@ (unable to statically define); /Minimum/: The value of 'Epsilon'.; /Notes/: 'Neato' only, only if @'Pack' 'DontPack'@+ | Dim Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: maximum of @10@; 'Sfdp', 'Fdp', 'Neato' only+ | Dimen Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: maximum of @10@; 'Sfdp', 'Fdp', 'Neato' only+ | Dir DirType -- ^ /Valid for/: E; /Default/: @'Forward'@ (directed), @'NoDir'@ (undirected)+ | DirEdgeConstraints DEConstraints -- ^ /Valid for/: G; /Default/: @'NoConstraints'@; /Parsing Default/: 'EdgeConstraints'; /Notes/: 'Neato' only+ | Distortion Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@+ | DPI Double -- ^ /Valid for/: G; /Default/: @96.0@, @0.0@; /Notes/: svg, bitmap output only; \"resolution\" is a synonym+ | EdgeURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only+ | EdgeTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only+ | EdgeTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only+ | Epsilon Double -- ^ /Valid for/: G; /Default/: @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@); /Notes/: 'Neato' only+ | ESep DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 3@; /Notes/: not 'Dot'+ | FillColor ColorList -- ^ /Valid for/: NEC; /Default/: @['WC' ('X11Color' 'LightGray') Nothing]@ (nodes), @['WC' ('X11Color' 'Black') Nothing]@ (clusters)+ | FixedSize NodeSize -- ^ /Valid for/: N; /Default/: @'GrowAsNeeded'@; /Parsing Default/: 'SetNodeSize'+ | FontColor Color -- ^ /Valid for/: ENGC; /Default/: @'X11Color' 'Black'@+ | FontName Text -- ^ /Valid for/: ENGC; /Default/: @\"Times-Roman\"@+ | FontNames SVGFontNames -- ^ /Valid for/: G; /Default/: @'SvgNames'@; /Notes/: svg only+ | FontPath Paths -- ^ /Valid for/: G; /Default/: system dependent+ | FontSize Double -- ^ /Valid for/: ENGC; /Default/: @14.0@; /Minimum/: @1.0@+ | ForceLabels Bool -- ^ /Valid for/: G; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: only for 'XLabel' attributes, requires Graphviz >= 2.29.0+ | GradientAngle Int -- ^ /Valid for/: NCG; /Default/: 0; /Notes/: requires Graphviz >= 2.29.0+ | Group Text -- ^ /Valid for/: N; /Default/: @\"\"@; /Notes/: 'Dot' only+ | HeadURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only+ | Head_LP Point -- ^ /Valid for/: E; /Notes/: write only, requires Graphviz >= 2.30.0+ | HeadClip Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'+ | HeadLabel Label -- ^ /Valid for/: E; /Default/: @'StrLabel' \"\"@+ | HeadPort PortPos -- ^ /Valid for/: E; /Default/: @'CompassPoint' 'CenterPoint'@+ | HeadTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only+ | HeadTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only+ | Height Double -- ^ /Valid for/: N; /Default/: @0.5@; /Minimum/: @0.02@+ | ID EscString -- ^ /Valid for/: GNE; /Default/: @\"\"@; /Notes/: svg, postscript, map only+ | Image Text -- ^ /Valid for/: N; /Default/: @\"\"@+ | ImagePath Paths -- ^ /Valid for/: G; /Default/: @'Paths' []@; /Notes/: Printing and parsing is OS-specific, requires Graphviz >= 2.29.0+ | ImageScale ScaleType -- ^ /Valid for/: N; /Default/: @'NoScale'@; /Parsing Default/: 'UniformScale'+ | InputScale Double -- ^ /Valid for/: N; /Default/: none; /Notes/: 'Fdp', 'Neato' only, a value of @0@ is equivalent to being @72@, requires Graphviz >= 2.36.0+ | Label Label -- ^ /Valid for/: ENGC; /Default/: @'StrLabel' \"\\N\"@ (nodes), @'StrLabel' \"\"@ (otherwise)+ | LabelURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only+ | LabelScheme LabelScheme -- ^ /Valid for/: G; /Default/: @'NotEdgeLabel'@; /Notes/: 'Sfdp' only, requires Graphviz >= 2.28.0+ | LabelAngle Double -- ^ /Valid for/: E; /Default/: @-25.0@; /Minimum/: @-180.0@+ | LabelDistance Double -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0.0@+ | LabelFloat Bool -- ^ /Valid for/: E; /Default/: @'False'@; /Parsing Default/: 'True'+ | LabelFontColor Color -- ^ /Valid for/: E; /Default/: @'X11Color' 'Black'@+ | LabelFontName Text -- ^ /Valid for/: E; /Default/: @\"Times-Roman\"@+ | LabelFontSize Double -- ^ /Valid for/: E; /Default/: @14.0@; /Minimum/: @1.0@+ | LabelJust Justification -- ^ /Valid for/: GC; /Default/: @'JCenter'@+ | LabelLoc VerticalPlacement -- ^ /Valid for/: GCN; /Default/: @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)+ | LabelTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only+ | LabelTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only+ | Landscape Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'+ | Layer LayerRange -- ^ /Valid for/: ENC; /Default/: @[]@+ | LayerListSep LayerListSep -- ^ /Valid for/: G; /Default/: @'LLSep' \",\"@; /Notes/: requires Graphviz >= 2.30.0+ | Layers LayerList -- ^ /Valid for/: G; /Default/: @'LL' []@+ | LayerSelect LayerRange -- ^ /Valid for/: G; /Default/: @[]@+ | LayerSep LayerSep -- ^ /Valid for/: G; /Default/: @'LSep' \" :\t\"@+ | Layout GraphvizCommand -- ^ /Valid for/: G+ | Len Double -- ^ /Valid for/: E; /Default/: @1.0@ ('Neato'), @0.3@ ('Fdp'); /Notes/: 'Fdp', 'Neato' only+ | Levels Int -- ^ /Valid for/: G; /Default/: @'maxBound'@; /Minimum/: @0@; /Notes/: 'Sfdp' only+ | LevelsGap Double -- ^ /Valid for/: G; /Default/: @0.0@; /Notes/: 'Neato' only+ | LHead Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: 'Dot' only+ | LHeight Double -- ^ /Valid for/: GC; /Notes/: write only, requires Graphviz >= 2.28.0+ | LPos Point -- ^ /Valid for/: EGC; /Notes/: write only+ | LTail Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: 'Dot' only+ | LWidth Double -- ^ /Valid for/: GC; /Notes/: write only, requires Graphviz >= 2.28.0+ | Margin DPoint -- ^ /Valid for/: NGC; /Default/: device dependent+ | MaxIter Int -- ^ /Valid for/: G; /Default/: @100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ ('Fdp'); /Notes/: 'Fdp', 'Neato' only+ | MCLimit Double -- ^ /Valid for/: G; /Default/: @1.0@; /Notes/: 'Dot' only+ | MinDist Double -- ^ /Valid for/: G; /Default/: @1.0@; /Minimum/: @0.0@; /Notes/: 'Circo' only+ | MinLen Int -- ^ /Valid for/: E; /Default/: @1@; /Minimum/: @0@; /Notes/: 'Dot' only+ | Mode ModeType -- ^ /Valid for/: G; /Default/: @'Major'@ (actually @'Spring'@ for 'Sfdp', but this isn't used as a default in this library); /Notes/: 'Neato', 'Sfdp' only+ | Model Model -- ^ /Valid for/: G; /Default/: @'ShortPath'@; /Notes/: 'Neato' only+ | Mosek Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: 'Neato' only; requires the Mosek software+ | NodeSep Double -- ^ /Valid for/: G; /Default/: @0.25@; /Minimum/: @0.02@+ | NoJustify Bool -- ^ /Valid for/: GCNE; /Default/: @'False'@; /Parsing Default/: 'True'+ | Normalize Normalized -- ^ /Valid for/: G; /Default/: @'NotNormalized'@; /Parsing Default/: 'IsNormalized'; /Notes/: not 'Dot'+ | Nslimit Double -- ^ /Valid for/: G; /Notes/: 'Dot' only+ | Nslimit1 Double -- ^ /Valid for/: G; /Notes/: 'Dot' only+ | Ordering Order -- ^ /Valid for/: GN; /Default/: none; /Notes/: 'Dot' only+ | Orientation Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @360.0@+ | OutputOrder OutputMode -- ^ /Valid for/: G; /Default/: @'BreadthFirst'@+ | Overlap Overlap -- ^ /Valid for/: G; /Default/: @'KeepOverlaps'@; /Parsing Default/: 'KeepOverlaps'; /Notes/: not 'Dot'+ | OverlapScaling Double -- ^ /Valid for/: G; /Default/: @-4@; /Minimum/: @-1.0e10@; /Notes/: 'PrismOverlap' only+ | OverlapShrink Bool -- ^ /Valid for/: G; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: 'PrismOverlap' only, requires Graphviz >= 2.36.0+ | Pack Pack -- ^ /Valid for/: G; /Default/: @'DontPack'@; /Parsing Default/: 'DoPack'+ | PackMode PackMode -- ^ /Valid for/: G; /Default/: @'PackNode'@+ | Pad DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 0.0555@ (4 points)+ | Page Point -- ^ /Valid for/: G+ | PageDir PageDir -- ^ /Valid for/: G; /Default/: @'Bl'@+ | PenColor Color -- ^ /Valid for/: C; /Default/: @'X11Color' 'Black'@+ | PenWidth Double -- ^ /Valid for/: CNE; /Default/: @1.0@; /Minimum/: @0.0@+ | Peripheries Int -- ^ /Valid for/: NC; /Default/: shape default (nodes), @1@ (clusters); /Minimum/: 0+ | Pin Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: 'Fdp', 'Neato' only+ | Pos Pos -- ^ /Valid for/: EN+ | QuadTree QuadType -- ^ /Valid for/: G; /Default/: @'NormalQT'@; /Parsing Default/: 'NormalQT'; /Notes/: 'Sfdp' only+ | Quantum Double -- ^ /Valid for/: G; /Default/: @0.0@; /Minimum/: @0.0@+ | Rank RankType -- ^ /Valid for/: S; /Notes/: 'Dot' only+ | RankDir RankDir -- ^ /Valid for/: G; /Default/: @'FromTop'@; /Notes/: 'Dot' only+ | RankSep [Double] -- ^ /Valid for/: G; /Default/: @[0.5]@ ('Dot'), @[1.0]@ ('Twopi'); /Minimum/: @[0.02]@; /Notes/: 'Twopi', 'Dot' only+ | Ratio Ratios -- ^ /Valid for/: G+ | Rects [Rect] -- ^ /Valid for/: N; /Notes/: write only+ | Regular Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'+ | ReMinCross Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: 'Dot' only+ | RepulsiveForce Double -- ^ /Valid for/: G; /Default/: @1.0@; /Minimum/: @0.0@; /Notes/: 'Sfdp' only+ | Root Root -- ^ /Valid for/: GN; /Default/: @'NodeName' \"\"@ (graphs), @'NotCentral'@ (nodes); /Parsing Default/: 'IsCentral'; /Notes/: 'Circo', 'Twopi' only+ | Rotate Int -- ^ /Valid for/: G; /Default/: @0@+ | Rotation Double -- ^ /Valid for/: G; /Default/: @0@; /Notes/: 'Sfdp' only, requires Graphviz >= 2.28.0+ | SameHead Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: 'Dot' only+ | SameTail Text -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: 'Dot' only+ | SamplePoints Int -- ^ /Valid for/: N; /Default/: @8@ (output), @20@ (overlap and image maps)+ | Scale DPoint -- ^ /Valid for/: G; /Notes/: Not 'Dot', requires Graphviz >= 2.28.0 (>= 2.38.0 for anything except 'TwoPi')+ | SearchSize Int -- ^ /Valid for/: G; /Default/: @30@; /Notes/: 'Dot' only+ | Sep DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 4@; /Notes/: not 'Dot'+ | Shape Shape -- ^ /Valid for/: N; /Default/: @'Ellipse'@+ | ShowBoxes Int -- ^ /Valid for/: ENG; /Default/: @0@; /Minimum/: @0@; /Notes/: 'Dot' only; used for debugging by printing PostScript guide boxes+ | Sides Int -- ^ /Valid for/: N; /Default/: @4@; /Minimum/: @0@+ | Size GraphSize -- ^ /Valid for/: G+ | Skew Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@+ | Smoothing SmoothType -- ^ /Valid for/: G; /Default/: @'NoSmooth'@; /Notes/: 'Sfdp' only+ | SortV Word16 -- ^ /Valid for/: GCN; /Default/: @0@; /Minimum/: @0@+ | Splines EdgeType -- ^ /Valid for/: G; /Default/: @'SplineEdges'@ ('Dot'), @'LineEdges'@ (other); /Parsing Default/: 'SplineEdges'+ | Start StartType -- ^ /Valid for/: G; /Default/: @'StartStyleSeed' 'RandomStyle' seed@ for some unknown fixed seed.; /Notes/: 'Fdp', 'Neato' only+ | Style [StyleItem] -- ^ /Valid for/: ENCG+ | StyleSheet Text -- ^ /Valid for/: G; /Default/: @\"\"@; /Notes/: svg only+ | TailURL EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only+ | Tail_LP Point -- ^ /Valid for/: E; /Notes/: write only, requires Graphviz >= 2.30.0+ | TailClip Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'+ | TailLabel Label -- ^ /Valid for/: E; /Default/: @'StrLabel' \"\"@+ | TailPort PortPos -- ^ /Valid for/: E; /Default/: @'CompassPoint' 'CenterPoint'@+ | TailTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only+ | TailTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only+ | Target EscString -- ^ /Valid for/: ENGC; /Default/: none; /Notes/: svg, map only+ | Tooltip EscString -- ^ /Valid for/: NEC; /Default/: @\"\"@; /Notes/: svg, cmap only+ | TrueColor Bool -- ^ /Valid for/: G; /Parsing Default/: 'True'; /Notes/: bitmap output only+ | Vertices [Point] -- ^ /Valid for/: N; /Notes/: write only+ | ViewPort ViewPort -- ^ /Valid for/: G; /Default/: none+ | VoroMargin Double -- ^ /Valid for/: G; /Default/: @0.05@; /Minimum/: @0.0@; /Notes/: not 'Dot'+ | Weight Number -- ^ /Valid for/: E; /Default/: @'Int' 1@; /Minimum/: @'Int' 0@ ('Dot'), @'Int' 1@ ('Neato','Fdp','Sfdp'); /Notes/: as of Graphviz 2.30: weights for dot need to be 'Int's+ | Width Double -- ^ /Valid for/: N; /Default/: @0.75@; /Minimum/: @0.01@+ | XDotVersion Version -- ^ /Valid for/: G; /Notes/: xdot only, requires Graphviz >= 2.34.0, equivalent to specifying version of xdot to be used+ | XLabel Label -- ^ /Valid for/: EN; /Default/: @'StrLabel' \"\"@; /Notes/: requires Graphviz >= 2.29.0+ | XLP Point -- ^ /Valid for/: EN; /Notes/: write only, requires Graphviz >= 2.29.0+ | UnknownAttribute AttributeName Text -- ^ /Valid for/: Assumed valid for all; the fields are 'Attribute' name and value respectively.+ deriving (Eq, Ord, Show, Read)++type Attributes = [Attribute]++-- | The name for an UnknownAttribute; must satisfy 'validUnknown'.+type AttributeName = Text++instance PrintDot Attribute where+ unqtDot (Damping v) = printField "Damping" v+ unqtDot (K v) = printField "K" v+ unqtDot (URL v) = printField "URL" v+ unqtDot (Area v) = printField "area" v+ unqtDot (ArrowHead v) = printField "arrowhead" v+ unqtDot (ArrowSize v) = printField "arrowsize" v+ unqtDot (ArrowTail v) = printField "arrowtail" v+ unqtDot (Background v) = printField "_background" v+ unqtDot (BoundingBox v) = printField "bb" v+ unqtDot (BgColor v) = printField "bgcolor" v+ unqtDot (Center v) = printField "center" v+ unqtDot (ClusterRank v) = printField "clusterrank" v+ unqtDot (Color v) = printField "color" v+ unqtDot (ColorScheme v) = printField "colorscheme" v+ unqtDot (Comment v) = printField "comment" v+ unqtDot (Compound v) = printField "compound" v+ unqtDot (Concentrate v) = printField "concentrate" v+ unqtDot (Constraint v) = printField "constraint" v+ unqtDot (Decorate v) = printField "decorate" v+ unqtDot (DefaultDist v) = printField "defaultdist" v+ unqtDot (Dim v) = printField "dim" v+ unqtDot (Dimen v) = printField "dimen" v+ unqtDot (Dir v) = printField "dir" v+ unqtDot (DirEdgeConstraints v) = printField "diredgeconstraints" v+ unqtDot (Distortion v) = printField "distortion" v+ unqtDot (DPI v) = printField "dpi" v+ unqtDot (EdgeURL v) = printField "edgeURL" v+ unqtDot (EdgeTarget v) = printField "edgetarget" v+ unqtDot (EdgeTooltip v) = printField "edgetooltip" v+ unqtDot (Epsilon v) = printField "epsilon" v+ unqtDot (ESep v) = printField "esep" v+ unqtDot (FillColor v) = printField "fillcolor" v+ unqtDot (FixedSize v) = printField "fixedsize" v+ unqtDot (FontColor v) = printField "fontcolor" v+ unqtDot (FontName v) = printField "fontname" v+ unqtDot (FontNames v) = printField "fontnames" v+ unqtDot (FontPath v) = printField "fontpath" v+ unqtDot (FontSize v) = printField "fontsize" v+ unqtDot (ForceLabels v) = printField "forcelabels" v+ unqtDot (GradientAngle v) = printField "gradientangle" v+ unqtDot (Group v) = printField "group" v+ unqtDot (HeadURL v) = printField "headURL" v+ unqtDot (Head_LP v) = printField "head_lp" v+ unqtDot (HeadClip v) = printField "headclip" v+ unqtDot (HeadLabel v) = printField "headlabel" v+ unqtDot (HeadPort v) = printField "headport" v+ unqtDot (HeadTarget v) = printField "headtarget" v+ unqtDot (HeadTooltip v) = printField "headtooltip" v+ unqtDot (Height v) = printField "height" v+ unqtDot (ID v) = printField "id" v+ unqtDot (Image v) = printField "image" v+ unqtDot (ImagePath v) = printField "imagepath" v+ unqtDot (ImageScale v) = printField "imagescale" v+ unqtDot (InputScale v) = printField "inputscale" v+ unqtDot (Label v) = printField "label" v+ unqtDot (LabelURL v) = printField "labelURL" v+ unqtDot (LabelScheme v) = printField "label_scheme" v+ unqtDot (LabelAngle v) = printField "labelangle" v+ unqtDot (LabelDistance v) = printField "labeldistance" v+ unqtDot (LabelFloat v) = printField "labelfloat" v+ unqtDot (LabelFontColor v) = printField "labelfontcolor" v+ unqtDot (LabelFontName v) = printField "labelfontname" v+ unqtDot (LabelFontSize v) = printField "labelfontsize" v+ unqtDot (LabelJust v) = printField "labeljust" v+ unqtDot (LabelLoc v) = printField "labelloc" v+ unqtDot (LabelTarget v) = printField "labeltarget" v+ unqtDot (LabelTooltip v) = printField "labeltooltip" v+ unqtDot (Landscape v) = printField "landscape" v+ unqtDot (Layer v) = printField "layer" v+ unqtDot (LayerListSep v) = printField "layerlistsep" v+ unqtDot (Layers v) = printField "layers" v+ unqtDot (LayerSelect v) = printField "layerselect" v+ unqtDot (LayerSep v) = printField "layersep" v+ unqtDot (Layout v) = printField "layout" v+ unqtDot (Len v) = printField "len" v+ unqtDot (Levels v) = printField "levels" v+ unqtDot (LevelsGap v) = printField "levelsgap" v+ unqtDot (LHead v) = printField "lhead" v+ unqtDot (LHeight v) = printField "LHeight" v+ unqtDot (LPos v) = printField "lp" v+ unqtDot (LTail v) = printField "ltail" v+ unqtDot (LWidth v) = printField "lwidth" v+ unqtDot (Margin v) = printField "margin" v+ unqtDot (MaxIter v) = printField "maxiter" v+ unqtDot (MCLimit v) = printField "mclimit" v+ unqtDot (MinDist v) = printField "mindist" v+ unqtDot (MinLen v) = printField "minlen" v+ unqtDot (Mode v) = printField "mode" v+ unqtDot (Model v) = printField "model" v+ unqtDot (Mosek v) = printField "mosek" v+ unqtDot (NodeSep v) = printField "nodesep" v+ unqtDot (NoJustify v) = printField "nojustify" v+ unqtDot (Normalize v) = printField "normalize" v+ unqtDot (Nslimit v) = printField "nslimit" v+ unqtDot (Nslimit1 v) = printField "nslimit1" v+ unqtDot (Ordering v) = printField "ordering" v+ unqtDot (Orientation v) = printField "orientation" v+ unqtDot (OutputOrder v) = printField "outputorder" v+ unqtDot (Overlap v) = printField "overlap" v+ unqtDot (OverlapScaling v) = printField "overlap_scaling" v+ unqtDot (OverlapShrink v) = printField "overlap_shrink" v+ unqtDot (Pack v) = printField "pack" v+ unqtDot (PackMode v) = printField "packmode" v+ unqtDot (Pad v) = printField "pad" v+ unqtDot (Page v) = printField "page" v+ unqtDot (PageDir v) = printField "pagedir" v+ unqtDot (PenColor v) = printField "pencolor" v+ unqtDot (PenWidth v) = printField "penwidth" v+ unqtDot (Peripheries v) = printField "peripheries" v+ unqtDot (Pin v) = printField "pin" v+ unqtDot (Pos v) = printField "pos" v+ unqtDot (QuadTree v) = printField "quadtree" v+ unqtDot (Quantum v) = printField "quantum" v+ unqtDot (Rank v) = printField "rank" v+ unqtDot (RankDir v) = printField "rankdir" v+ unqtDot (RankSep v) = printField "ranksep" v+ unqtDot (Ratio v) = printField "ratio" v+ unqtDot (Rects v) = printField "rects" v+ unqtDot (Regular v) = printField "regular" v+ unqtDot (ReMinCross v) = printField "remincross" v+ unqtDot (RepulsiveForce v) = printField "repulsiveforce" v+ unqtDot (Root v) = printField "root" v+ unqtDot (Rotate v) = printField "rotate" v+ unqtDot (Rotation v) = printField "rotation" v+ unqtDot (SameHead v) = printField "samehead" v+ unqtDot (SameTail v) = printField "sametail" v+ unqtDot (SamplePoints v) = printField "samplepoints" v+ unqtDot (Scale v) = printField "scale" v+ unqtDot (SearchSize v) = printField "searchsize" v+ unqtDot (Sep v) = printField "sep" v+ unqtDot (Shape v) = printField "shape" v+ unqtDot (ShowBoxes v) = printField "showboxes" v+ unqtDot (Sides v) = printField "sides" v+ unqtDot (Size v) = printField "size" v+ unqtDot (Skew v) = printField "skew" v+ unqtDot (Smoothing v) = printField "smoothing" v+ unqtDot (SortV v) = printField "sortv" v+ unqtDot (Splines v) = printField "splines" v+ unqtDot (Start v) = printField "start" v+ unqtDot (Style v) = printField "style" v+ unqtDot (StyleSheet v) = printField "stylesheet" v+ unqtDot (TailURL v) = printField "tailURL" v+ unqtDot (Tail_LP v) = printField "tail_lp" v+ unqtDot (TailClip v) = printField "tailclip" v+ unqtDot (TailLabel v) = printField "taillabel" v+ unqtDot (TailPort v) = printField "tailport" v+ unqtDot (TailTarget v) = printField "tailtarget" v+ unqtDot (TailTooltip v) = printField "tailtooltip" v+ unqtDot (Target v) = printField "target" v+ unqtDot (Tooltip v) = printField "tooltip" v+ unqtDot (TrueColor v) = printField "truecolor" v+ unqtDot (Vertices v) = printField "vertices" v+ unqtDot (ViewPort v) = printField "viewport" v+ unqtDot (VoroMargin v) = printField "voro_margin" v+ unqtDot (Weight v) = printField "weight" v+ unqtDot (Width v) = printField "width" v+ unqtDot (XDotVersion v) = printField "xdotversion" v+ unqtDot (XLabel v) = printField "xlabel" v+ unqtDot (XLP v) = printField "xlp" v+ unqtDot (UnknownAttribute a v) = toDot a <> equals <> toDot v++ listToDot = unqtListToDot++instance ParseDot Attribute where+ parseUnqt = stringParse (concat [ parseField Damping "Damping"+ , parseField K "K"+ , parseFields URL ["URL", "href"]+ , parseField Area "area"+ , parseField ArrowHead "arrowhead"+ , parseField ArrowSize "arrowsize"+ , parseField ArrowTail "arrowtail"+ , parseField Background "_background"+ , parseField BoundingBox "bb"+ , parseField BgColor "bgcolor"+ , parseFieldBool Center "center"+ , parseField ClusterRank "clusterrank"+ , parseField Color "color"+ , parseField ColorScheme "colorscheme"+ , parseField Comment "comment"+ , parseFieldBool Compound "compound"+ , parseFieldBool Concentrate "concentrate"+ , parseFieldBool Constraint "constraint"+ , parseFieldBool Decorate "decorate"+ , parseField DefaultDist "defaultdist"+ , parseField Dim "dim"+ , parseField Dimen "dimen"+ , parseField Dir "dir"+ , parseFieldDef DirEdgeConstraints EdgeConstraints "diredgeconstraints"+ , parseField Distortion "distortion"+ , parseFields DPI ["dpi", "resolution"]+ , parseFields EdgeURL ["edgeURL", "edgehref"]+ , parseField EdgeTarget "edgetarget"+ , parseField EdgeTooltip "edgetooltip"+ , parseField Epsilon "epsilon"+ , parseField ESep "esep"+ , parseField FillColor "fillcolor"+ , parseFieldDef FixedSize SetNodeSize "fixedsize"+ , parseField FontColor "fontcolor"+ , parseField FontName "fontname"+ , parseField FontNames "fontnames"+ , parseField FontPath "fontpath"+ , parseField FontSize "fontsize"+ , parseFieldBool ForceLabels "forcelabels"+ , parseField GradientAngle "gradientangle"+ , parseField Group "group"+ , parseFields HeadURL ["headURL", "headhref"]+ , parseField Head_LP "head_lp"+ , parseFieldBool HeadClip "headclip"+ , parseField HeadLabel "headlabel"+ , parseField HeadPort "headport"+ , parseField HeadTarget "headtarget"+ , parseField HeadTooltip "headtooltip"+ , parseField Height "height"+ , parseField ID "id"+ , parseField Image "image"+ , parseField ImagePath "imagepath"+ , parseFieldDef ImageScale UniformScale "imagescale"+ , parseField InputScale "inputscale"+ , parseField Label "label"+ , parseFields LabelURL ["labelURL", "labelhref"]+ , parseField LabelScheme "label_scheme"+ , parseField LabelAngle "labelangle"+ , parseField LabelDistance "labeldistance"+ , parseFieldBool LabelFloat "labelfloat"+ , parseField LabelFontColor "labelfontcolor"+ , parseField LabelFontName "labelfontname"+ , parseField LabelFontSize "labelfontsize"+ , parseField LabelJust "labeljust"+ , parseField LabelLoc "labelloc"+ , parseField LabelTarget "labeltarget"+ , parseField LabelTooltip "labeltooltip"+ , parseFieldBool Landscape "landscape"+ , parseField Layer "layer"+ , parseField LayerListSep "layerlistsep"+ , parseField Layers "layers"+ , parseField LayerSelect "layerselect"+ , parseField LayerSep "layersep"+ , parseField Layout "layout"+ , parseField Len "len"+ , parseField Levels "levels"+ , parseField LevelsGap "levelsgap"+ , parseField LHead "lhead"+ , parseField LHeight "LHeight"+ , parseField LPos "lp"+ , parseField LTail "ltail"+ , parseField LWidth "lwidth"+ , parseField Margin "margin"+ , parseField MaxIter "maxiter"+ , parseField MCLimit "mclimit"+ , parseField MinDist "mindist"+ , parseField MinLen "minlen"+ , parseField Mode "mode"+ , parseField Model "model"+ , parseFieldBool Mosek "mosek"+ , parseField NodeSep "nodesep"+ , parseFieldBool NoJustify "nojustify"+ , parseFieldDef Normalize IsNormalized "normalize"+ , parseField Nslimit "nslimit"+ , parseField Nslimit1 "nslimit1"+ , parseField Ordering "ordering"+ , parseField Orientation "orientation"+ , parseField OutputOrder "outputorder"+ , parseFieldDef Overlap KeepOverlaps "overlap"+ , parseField OverlapScaling "overlap_scaling"+ , parseFieldBool OverlapShrink "overlap_shrink"+ , parseFieldDef Pack DoPack "pack"+ , parseField PackMode "packmode"+ , parseField Pad "pad"+ , parseField Page "page"+ , parseField PageDir "pagedir"+ , parseField PenColor "pencolor"+ , parseField PenWidth "penwidth"+ , parseField Peripheries "peripheries"+ , parseFieldBool Pin "pin"+ , parseField Pos "pos"+ , parseFieldDef QuadTree NormalQT "quadtree"+ , parseField Quantum "quantum"+ , parseField Rank "rank"+ , parseField RankDir "rankdir"+ , parseField RankSep "ranksep"+ , parseField Ratio "ratio"+ , parseField Rects "rects"+ , parseFieldBool Regular "regular"+ , parseFieldBool ReMinCross "remincross"+ , parseField RepulsiveForce "repulsiveforce"+ , parseFieldDef Root IsCentral "root"+ , parseField Rotate "rotate"+ , parseField Rotation "rotation"+ , parseField SameHead "samehead"+ , parseField SameTail "sametail"+ , parseField SamplePoints "samplepoints"+ , parseField Scale "scale"+ , parseField SearchSize "searchsize"+ , parseField Sep "sep"+ , parseField Shape "shape"+ , parseField ShowBoxes "showboxes"+ , parseField Sides "sides"+ , parseField Size "size"+ , parseField Skew "skew"+ , parseField Smoothing "smoothing"+ , parseField SortV "sortv"+ , parseFieldDef Splines SplineEdges "splines"+ , parseField Start "start"+ , parseField Style "style"+ , parseField StyleSheet "stylesheet"+ , parseFields TailURL ["tailURL", "tailhref"]+ , parseField Tail_LP "tail_lp"+ , parseFieldBool TailClip "tailclip"+ , parseField TailLabel "taillabel"+ , parseField TailPort "tailport"+ , parseField TailTarget "tailtarget"+ , parseField TailTooltip "tailtooltip"+ , parseField Target "target"+ , parseField Tooltip "tooltip"+ , parseFieldBool TrueColor "truecolor"+ , parseField Vertices "vertices"+ , parseField ViewPort "viewport"+ , parseField VoroMargin "voro_margin"+ , parseField Weight "weight"+ , parseField Width "width"+ , parseField XDotVersion "xdotversion"+ , parseField XLabel "xlabel"+ , parseField XLP "xlp"+ ])+ `onFail`+ do attrName <- stringBlock+ liftEqParse ("UnknownAttribute (" ++ T.unpack attrName ++ ")")+ (UnknownAttribute attrName)++ parse = parseUnqt++ parseList = parseUnqtList++-- | Determine if this 'Attribute' is valid for use with Graphs.+usedByGraphs :: Attribute -> Bool+usedByGraphs Damping{} = True+usedByGraphs K{} = True+usedByGraphs URL{} = True+usedByGraphs Background{} = True+usedByGraphs BoundingBox{} = True+usedByGraphs BgColor{} = True+usedByGraphs Center{} = True+usedByGraphs ClusterRank{} = True+usedByGraphs ColorScheme{} = True+usedByGraphs Comment{} = True+usedByGraphs Compound{} = True+usedByGraphs Concentrate{} = True+usedByGraphs DefaultDist{} = True+usedByGraphs Dim{} = True+usedByGraphs Dimen{} = True+usedByGraphs DirEdgeConstraints{} = True+usedByGraphs DPI{} = True+usedByGraphs Epsilon{} = True+usedByGraphs ESep{} = True+usedByGraphs FontColor{} = True+usedByGraphs FontName{} = True+usedByGraphs FontNames{} = True+usedByGraphs FontPath{} = True+usedByGraphs FontSize{} = True+usedByGraphs ForceLabels{} = True+usedByGraphs GradientAngle{} = True+usedByGraphs ID{} = True+usedByGraphs ImagePath{} = True+usedByGraphs Label{} = True+usedByGraphs LabelScheme{} = True+usedByGraphs LabelJust{} = True+usedByGraphs LabelLoc{} = True+usedByGraphs Landscape{} = True+usedByGraphs LayerListSep{} = True+usedByGraphs Layers{} = True+usedByGraphs LayerSelect{} = True+usedByGraphs LayerSep{} = True+usedByGraphs Layout{} = True+usedByGraphs Levels{} = True+usedByGraphs LevelsGap{} = True+usedByGraphs LHeight{} = True+usedByGraphs LPos{} = True+usedByGraphs LWidth{} = True+usedByGraphs Margin{} = True+usedByGraphs MaxIter{} = True+usedByGraphs MCLimit{} = True+usedByGraphs MinDist{} = True+usedByGraphs Mode{} = True+usedByGraphs Model{} = True+usedByGraphs Mosek{} = True+usedByGraphs NodeSep{} = True+usedByGraphs NoJustify{} = True+usedByGraphs Normalize{} = True+usedByGraphs Nslimit{} = True+usedByGraphs Nslimit1{} = True+usedByGraphs Ordering{} = True+usedByGraphs OutputOrder{} = True+usedByGraphs Overlap{} = True+usedByGraphs OverlapScaling{} = True+usedByGraphs OverlapShrink{} = True+usedByGraphs Pack{} = True+usedByGraphs PackMode{} = True+usedByGraphs Pad{} = True+usedByGraphs Page{} = True+usedByGraphs PageDir{} = True+usedByGraphs QuadTree{} = True+usedByGraphs Quantum{} = True+usedByGraphs RankDir{} = True+usedByGraphs RankSep{} = True+usedByGraphs Ratio{} = True+usedByGraphs ReMinCross{} = True+usedByGraphs RepulsiveForce{} = True+usedByGraphs Root{} = True+usedByGraphs Rotate{} = True+usedByGraphs Rotation{} = True+usedByGraphs Scale{} = True+usedByGraphs SearchSize{} = True+usedByGraphs Sep{} = True+usedByGraphs ShowBoxes{} = True+usedByGraphs Size{} = True+usedByGraphs Smoothing{} = True+usedByGraphs SortV{} = True+usedByGraphs Splines{} = True+usedByGraphs Start{} = True+usedByGraphs Style{} = True+usedByGraphs StyleSheet{} = True+usedByGraphs Target{} = True+usedByGraphs TrueColor{} = True+usedByGraphs ViewPort{} = True+usedByGraphs VoroMargin{} = True+usedByGraphs XDotVersion{} = True+usedByGraphs UnknownAttribute{} = True+usedByGraphs _ = False++-- | Determine if this 'Attribute' is valid for use with Clusters.+usedByClusters :: Attribute -> Bool+usedByClusters K{} = True+usedByClusters URL{} = True+usedByClusters Area{} = True+usedByClusters BgColor{} = True+usedByClusters Color{} = True+usedByClusters ColorScheme{} = True+usedByClusters FillColor{} = True+usedByClusters FontColor{} = True+usedByClusters FontName{} = True+usedByClusters FontSize{} = True+usedByClusters GradientAngle{} = True+usedByClusters Label{} = True+usedByClusters LabelJust{} = True+usedByClusters LabelLoc{} = True+usedByClusters Layer{} = True+usedByClusters LHeight{} = True+usedByClusters LPos{} = True+usedByClusters LWidth{} = True+usedByClusters Margin{} = True+usedByClusters NoJustify{} = True+usedByClusters PenColor{} = True+usedByClusters PenWidth{} = True+usedByClusters Peripheries{} = True+usedByClusters Rank{} = True+usedByClusters SortV{} = True+usedByClusters Style{} = True+usedByClusters Target{} = True+usedByClusters Tooltip{} = True+usedByClusters UnknownAttribute{} = True+usedByClusters _ = False++-- | Determine if this 'Attribute' is valid for use with SubGraphs.+usedBySubGraphs :: Attribute -> Bool+usedBySubGraphs Rank{} = True+usedBySubGraphs UnknownAttribute{} = True+usedBySubGraphs _ = False++-- | Determine if this 'Attribute' is valid for use with Nodes.+usedByNodes :: Attribute -> Bool+usedByNodes URL{} = True+usedByNodes Area{} = True+usedByNodes Color{} = True+usedByNodes ColorScheme{} = True+usedByNodes Comment{} = True+usedByNodes Distortion{} = True+usedByNodes FillColor{} = True+usedByNodes FixedSize{} = True+usedByNodes FontColor{} = True+usedByNodes FontName{} = True+usedByNodes FontSize{} = True+usedByNodes GradientAngle{} = True+usedByNodes Group{} = True+usedByNodes Height{} = True+usedByNodes ID{} = True+usedByNodes Image{} = True+usedByNodes ImageScale{} = True+usedByNodes InputScale{} = True+usedByNodes Label{} = True+usedByNodes LabelLoc{} = True+usedByNodes Layer{} = True+usedByNodes Margin{} = True+usedByNodes NoJustify{} = True+usedByNodes Ordering{} = True+usedByNodes Orientation{} = True+usedByNodes PenWidth{} = True+usedByNodes Peripheries{} = True+usedByNodes Pin{} = True+usedByNodes Pos{} = True+usedByNodes Rects{} = True+usedByNodes Regular{} = True+usedByNodes Root{} = True+usedByNodes SamplePoints{} = True+usedByNodes Shape{} = True+usedByNodes ShowBoxes{} = True+usedByNodes Sides{} = True+usedByNodes Skew{} = True+usedByNodes SortV{} = True+usedByNodes Style{} = True+usedByNodes Target{} = True+usedByNodes Tooltip{} = True+usedByNodes Vertices{} = True+usedByNodes Width{} = True+usedByNodes XLabel{} = True+usedByNodes XLP{} = True+usedByNodes UnknownAttribute{} = True+usedByNodes _ = False++-- | Determine if this 'Attribute' is valid for use with Edges.+usedByEdges :: Attribute -> Bool+usedByEdges URL{} = True+usedByEdges ArrowHead{} = True+usedByEdges ArrowSize{} = True+usedByEdges ArrowTail{} = True+usedByEdges Color{} = True+usedByEdges ColorScheme{} = True+usedByEdges Comment{} = True+usedByEdges Constraint{} = True+usedByEdges Decorate{} = True+usedByEdges Dir{} = True+usedByEdges EdgeURL{} = True+usedByEdges EdgeTarget{} = True+usedByEdges EdgeTooltip{} = True+usedByEdges FillColor{} = True+usedByEdges FontColor{} = True+usedByEdges FontName{} = True+usedByEdges FontSize{} = True+usedByEdges HeadURL{} = True+usedByEdges Head_LP{} = True+usedByEdges HeadClip{} = True+usedByEdges HeadLabel{} = True+usedByEdges HeadPort{} = True+usedByEdges HeadTarget{} = True+usedByEdges HeadTooltip{} = True+usedByEdges ID{} = True+usedByEdges Label{} = True+usedByEdges LabelURL{} = True+usedByEdges LabelAngle{} = True+usedByEdges LabelDistance{} = True+usedByEdges LabelFloat{} = True+usedByEdges LabelFontColor{} = True+usedByEdges LabelFontName{} = True+usedByEdges LabelFontSize{} = True+usedByEdges LabelTarget{} = True+usedByEdges LabelTooltip{} = True+usedByEdges Layer{} = True+usedByEdges Len{} = True+usedByEdges LHead{} = True+usedByEdges LPos{} = True+usedByEdges LTail{} = True+usedByEdges MinLen{} = True+usedByEdges NoJustify{} = True+usedByEdges PenWidth{} = True+usedByEdges Pos{} = True+usedByEdges SameHead{} = True+usedByEdges SameTail{} = True+usedByEdges ShowBoxes{} = True+usedByEdges Style{} = True+usedByEdges TailURL{} = True+usedByEdges Tail_LP{} = True+usedByEdges TailClip{} = True+usedByEdges TailLabel{} = True+usedByEdges TailPort{} = True+usedByEdges TailTarget{} = True+usedByEdges TailTooltip{} = True+usedByEdges Target{} = True+usedByEdges Tooltip{} = True+usedByEdges Weight{} = True+usedByEdges XLabel{} = True+usedByEdges XLP{} = True+usedByEdges UnknownAttribute{} = True+usedByEdges _ = False++-- | Determine if two 'Attributes' are the same type of 'Attribute'.+sameAttribute :: Attribute -> Attribute -> Bool+sameAttribute Damping{} Damping{} = True+sameAttribute K{} K{} = True+sameAttribute URL{} URL{} = True+sameAttribute Area{} Area{} = True+sameAttribute ArrowHead{} ArrowHead{} = True+sameAttribute ArrowSize{} ArrowSize{} = True+sameAttribute ArrowTail{} ArrowTail{} = True+sameAttribute Background{} Background{} = True+sameAttribute BoundingBox{} BoundingBox{} = True+sameAttribute BgColor{} BgColor{} = True+sameAttribute Center{} Center{} = True+sameAttribute ClusterRank{} ClusterRank{} = True+sameAttribute Color{} Color{} = True+sameAttribute ColorScheme{} ColorScheme{} = True+sameAttribute Comment{} Comment{} = True+sameAttribute Compound{} Compound{} = True+sameAttribute Concentrate{} Concentrate{} = True+sameAttribute Constraint{} Constraint{} = True+sameAttribute Decorate{} Decorate{} = True+sameAttribute DefaultDist{} DefaultDist{} = True+sameAttribute Dim{} Dim{} = True+sameAttribute Dimen{} Dimen{} = True+sameAttribute Dir{} Dir{} = True+sameAttribute DirEdgeConstraints{} DirEdgeConstraints{} = True+sameAttribute Distortion{} Distortion{} = True+sameAttribute DPI{} DPI{} = True+sameAttribute EdgeURL{} EdgeURL{} = True+sameAttribute EdgeTarget{} EdgeTarget{} = True+sameAttribute EdgeTooltip{} EdgeTooltip{} = True+sameAttribute Epsilon{} Epsilon{} = True+sameAttribute ESep{} ESep{} = True+sameAttribute FillColor{} FillColor{} = True+sameAttribute FixedSize{} FixedSize{} = True+sameAttribute FontColor{} FontColor{} = True+sameAttribute FontName{} FontName{} = True+sameAttribute FontNames{} FontNames{} = True+sameAttribute FontPath{} FontPath{} = True+sameAttribute FontSize{} FontSize{} = True+sameAttribute ForceLabels{} ForceLabels{} = True+sameAttribute GradientAngle{} GradientAngle{} = True+sameAttribute Group{} Group{} = True+sameAttribute HeadURL{} HeadURL{} = True+sameAttribute Head_LP{} Head_LP{} = True+sameAttribute HeadClip{} HeadClip{} = True+sameAttribute HeadLabel{} HeadLabel{} = True+sameAttribute HeadPort{} HeadPort{} = True+sameAttribute HeadTarget{} HeadTarget{} = True+sameAttribute HeadTooltip{} HeadTooltip{} = True+sameAttribute Height{} Height{} = True+sameAttribute ID{} ID{} = True+sameAttribute Image{} Image{} = True+sameAttribute ImagePath{} ImagePath{} = True+sameAttribute ImageScale{} ImageScale{} = True+sameAttribute InputScale{} InputScale{} = True+sameAttribute Label{} Label{} = True+sameAttribute LabelURL{} LabelURL{} = True+sameAttribute LabelScheme{} LabelScheme{} = True+sameAttribute LabelAngle{} LabelAngle{} = True+sameAttribute LabelDistance{} LabelDistance{} = True+sameAttribute LabelFloat{} LabelFloat{} = True+sameAttribute LabelFontColor{} LabelFontColor{} = True+sameAttribute LabelFontName{} LabelFontName{} = True+sameAttribute LabelFontSize{} LabelFontSize{} = True+sameAttribute LabelJust{} LabelJust{} = True+sameAttribute LabelLoc{} LabelLoc{} = True+sameAttribute LabelTarget{} LabelTarget{} = True+sameAttribute LabelTooltip{} LabelTooltip{} = True+sameAttribute Landscape{} Landscape{} = True+sameAttribute Layer{} Layer{} = True+sameAttribute LayerListSep{} LayerListSep{} = True+sameAttribute Layers{} Layers{} = True+sameAttribute LayerSelect{} LayerSelect{} = True+sameAttribute LayerSep{} LayerSep{} = True+sameAttribute Layout{} Layout{} = True+sameAttribute Len{} Len{} = True+sameAttribute Levels{} Levels{} = True+sameAttribute LevelsGap{} LevelsGap{} = True+sameAttribute LHead{} LHead{} = True+sameAttribute LHeight{} LHeight{} = True+sameAttribute LPos{} LPos{} = True+sameAttribute LTail{} LTail{} = True+sameAttribute LWidth{} LWidth{} = True+sameAttribute Margin{} Margin{} = True+sameAttribute MaxIter{} MaxIter{} = True+sameAttribute MCLimit{} MCLimit{} = True+sameAttribute MinDist{} MinDist{} = True+sameAttribute MinLen{} MinLen{} = True+sameAttribute Mode{} Mode{} = True+sameAttribute Model{} Model{} = True+sameAttribute Mosek{} Mosek{} = True+sameAttribute NodeSep{} NodeSep{} = True+sameAttribute NoJustify{} NoJustify{} = True+sameAttribute Normalize{} Normalize{} = True+sameAttribute Nslimit{} Nslimit{} = True+sameAttribute Nslimit1{} Nslimit1{} = True+sameAttribute Ordering{} Ordering{} = True+sameAttribute Orientation{} Orientation{} = True+sameAttribute OutputOrder{} OutputOrder{} = True+sameAttribute Overlap{} Overlap{} = True+sameAttribute OverlapScaling{} OverlapScaling{} = True+sameAttribute OverlapShrink{} OverlapShrink{} = True+sameAttribute Pack{} Pack{} = True+sameAttribute PackMode{} PackMode{} = True+sameAttribute Pad{} Pad{} = True+sameAttribute Page{} Page{} = True+sameAttribute PageDir{} PageDir{} = True+sameAttribute PenColor{} PenColor{} = True+sameAttribute PenWidth{} PenWidth{} = True+sameAttribute Peripheries{} Peripheries{} = True+sameAttribute Pin{} Pin{} = True+sameAttribute Pos{} Pos{} = True+sameAttribute QuadTree{} QuadTree{} = True+sameAttribute Quantum{} Quantum{} = True+sameAttribute Rank{} Rank{} = True+sameAttribute RankDir{} RankDir{} = True+sameAttribute RankSep{} RankSep{} = True+sameAttribute Ratio{} Ratio{} = True+sameAttribute Rects{} Rects{} = True+sameAttribute Regular{} Regular{} = True+sameAttribute ReMinCross{} ReMinCross{} = True+sameAttribute RepulsiveForce{} RepulsiveForce{} = True+sameAttribute Root{} Root{} = True+sameAttribute Rotate{} Rotate{} = True+sameAttribute Rotation{} Rotation{} = True+sameAttribute SameHead{} SameHead{} = True+sameAttribute SameTail{} SameTail{} = True+sameAttribute SamplePoints{} SamplePoints{} = True+sameAttribute Scale{} Scale{} = True+sameAttribute SearchSize{} SearchSize{} = True+sameAttribute Sep{} Sep{} = True+sameAttribute Shape{} Shape{} = True+sameAttribute ShowBoxes{} ShowBoxes{} = True+sameAttribute Sides{} Sides{} = True+sameAttribute Size{} Size{} = True+sameAttribute Skew{} Skew{} = True+sameAttribute Smoothing{} Smoothing{} = True+sameAttribute SortV{} SortV{} = True+sameAttribute Splines{} Splines{} = True+sameAttribute Start{} Start{} = True+sameAttribute Style{} Style{} = True+sameAttribute StyleSheet{} StyleSheet{} = True+sameAttribute TailURL{} TailURL{} = True+sameAttribute Tail_LP{} Tail_LP{} = True+sameAttribute TailClip{} TailClip{} = True+sameAttribute TailLabel{} TailLabel{} = True+sameAttribute TailPort{} TailPort{} = True+sameAttribute TailTarget{} TailTarget{} = True+sameAttribute TailTooltip{} TailTooltip{} = True+sameAttribute Target{} Target{} = True+sameAttribute Tooltip{} Tooltip{} = True+sameAttribute TrueColor{} TrueColor{} = True+sameAttribute Vertices{} Vertices{} = True+sameAttribute ViewPort{} ViewPort{} = True+sameAttribute VoroMargin{} VoroMargin{} = True+sameAttribute Weight{} Weight{} = True+sameAttribute Width{} Width{} = True+sameAttribute XDotVersion{} XDotVersion{} = True+sameAttribute XLabel{} XLabel{} = True+sameAttribute XLP{} XLP{} = True+sameAttribute (UnknownAttribute a1 _) (UnknownAttribute a2 _) = a1 == a2+sameAttribute _ _ = False++-- | Return the default value for a specific 'Attribute' if possible; graph/cluster values are preferred over node/edge values.+defaultAttributeValue :: Attribute -> Maybe Attribute+defaultAttributeValue Damping{} = Just $ Damping 0.99+defaultAttributeValue K{} = Just $ K 0.3+defaultAttributeValue URL{} = Just $ URL ""+defaultAttributeValue Area{} = Just $ Area 1.0+defaultAttributeValue ArrowHead{} = Just $ ArrowHead normal+defaultAttributeValue ArrowSize{} = Just $ ArrowSize 1.0+defaultAttributeValue ArrowTail{} = Just $ ArrowTail normal+defaultAttributeValue Background{} = Just $ Background ""+defaultAttributeValue BgColor{} = Just $ BgColor []+defaultAttributeValue Center{} = Just $ Center False+defaultAttributeValue ClusterRank{} = Just $ ClusterRank Local+defaultAttributeValue Color{} = Just $ Color [toWColor Black]+defaultAttributeValue ColorScheme{} = Just $ ColorScheme X11+defaultAttributeValue Comment{} = Just $ Comment ""+defaultAttributeValue Compound{} = Just $ Compound False+defaultAttributeValue Concentrate{} = Just $ Concentrate False+defaultAttributeValue Constraint{} = Just $ Constraint True+defaultAttributeValue Decorate{} = Just $ Decorate False+defaultAttributeValue Dim{} = Just $ Dim 2+defaultAttributeValue Dimen{} = Just $ Dimen 2+defaultAttributeValue DirEdgeConstraints{} = Just $ DirEdgeConstraints NoConstraints+defaultAttributeValue Distortion{} = Just $ Distortion 0.0+defaultAttributeValue DPI{} = Just $ DPI 96.0+defaultAttributeValue EdgeURL{} = Just $ EdgeURL ""+defaultAttributeValue EdgeTooltip{} = Just $ EdgeTooltip ""+defaultAttributeValue ESep{} = Just $ ESep (DVal 3)+defaultAttributeValue FillColor{} = Just $ FillColor [toWColor Black]+defaultAttributeValue FixedSize{} = Just $ FixedSize GrowAsNeeded+defaultAttributeValue FontColor{} = Just $ FontColor (X11Color Black)+defaultAttributeValue FontName{} = Just $ FontName "Times-Roman"+defaultAttributeValue FontNames{} = Just $ FontNames SvgNames+defaultAttributeValue FontSize{} = Just $ FontSize 14.0+defaultAttributeValue ForceLabels{} = Just $ ForceLabels True+defaultAttributeValue GradientAngle{} = Just $ GradientAngle 0+defaultAttributeValue Group{} = Just $ Group ""+defaultAttributeValue HeadURL{} = Just $ HeadURL ""+defaultAttributeValue HeadClip{} = Just $ HeadClip True+defaultAttributeValue HeadLabel{} = Just $ HeadLabel (StrLabel "")+defaultAttributeValue HeadPort{} = Just $ HeadPort (CompassPoint CenterPoint)+defaultAttributeValue HeadTarget{} = Just $ HeadTarget ""+defaultAttributeValue HeadTooltip{} = Just $ HeadTooltip ""+defaultAttributeValue Height{} = Just $ Height 0.5+defaultAttributeValue ID{} = Just $ ID ""+defaultAttributeValue Image{} = Just $ Image ""+defaultAttributeValue ImagePath{} = Just $ ImagePath (Paths [])+defaultAttributeValue ImageScale{} = Just $ ImageScale NoScale+defaultAttributeValue Label{} = Just $ Label (StrLabel "")+defaultAttributeValue LabelURL{} = Just $ LabelURL ""+defaultAttributeValue LabelScheme{} = Just $ LabelScheme NotEdgeLabel+defaultAttributeValue LabelAngle{} = Just $ LabelAngle (-25.0)+defaultAttributeValue LabelDistance{} = Just $ LabelDistance 1.0+defaultAttributeValue LabelFloat{} = Just $ LabelFloat False+defaultAttributeValue LabelFontColor{} = Just $ LabelFontColor (X11Color Black)+defaultAttributeValue LabelFontName{} = Just $ LabelFontName "Times-Roman"+defaultAttributeValue LabelFontSize{} = Just $ LabelFontSize 14.0+defaultAttributeValue LabelJust{} = Just $ LabelJust JCenter+defaultAttributeValue LabelLoc{} = Just $ LabelLoc VTop+defaultAttributeValue LabelTarget{} = Just $ LabelTarget ""+defaultAttributeValue LabelTooltip{} = Just $ LabelTooltip ""+defaultAttributeValue Landscape{} = Just $ Landscape False+defaultAttributeValue Layer{} = Just $ Layer []+defaultAttributeValue LayerListSep{} = Just $ LayerListSep (LLSep ",")+defaultAttributeValue Layers{} = Just $ Layers (LL [])+defaultAttributeValue LayerSelect{} = Just $ LayerSelect []+defaultAttributeValue LayerSep{} = Just $ LayerSep (LSep " :\t")+defaultAttributeValue Levels{} = Just $ Levels maxBound+defaultAttributeValue LevelsGap{} = Just $ LevelsGap 0.0+defaultAttributeValue LHead{} = Just $ LHead ""+defaultAttributeValue LTail{} = Just $ LTail ""+defaultAttributeValue MCLimit{} = Just $ MCLimit 1.0+defaultAttributeValue MinDist{} = Just $ MinDist 1.0+defaultAttributeValue MinLen{} = Just $ MinLen 1+defaultAttributeValue Mode{} = Just $ Mode Major+defaultAttributeValue Model{} = Just $ Model ShortPath+defaultAttributeValue Mosek{} = Just $ Mosek False+defaultAttributeValue NodeSep{} = Just $ NodeSep 0.25+defaultAttributeValue NoJustify{} = Just $ NoJustify False+defaultAttributeValue Normalize{} = Just $ Normalize NotNormalized+defaultAttributeValue Orientation{} = Just $ Orientation 0.0+defaultAttributeValue OutputOrder{} = Just $ OutputOrder BreadthFirst+defaultAttributeValue Overlap{} = Just $ Overlap KeepOverlaps+defaultAttributeValue OverlapScaling{} = Just $ OverlapScaling (-4)+defaultAttributeValue OverlapShrink{} = Just $ OverlapShrink True+defaultAttributeValue Pack{} = Just $ Pack DontPack+defaultAttributeValue PackMode{} = Just $ PackMode PackNode+defaultAttributeValue Pad{} = Just $ Pad (DVal 0.0555)+defaultAttributeValue PageDir{} = Just $ PageDir Bl+defaultAttributeValue PenColor{} = Just $ PenColor (X11Color Black)+defaultAttributeValue PenWidth{} = Just $ PenWidth 1.0+defaultAttributeValue Peripheries{} = Just $ Peripheries 1+defaultAttributeValue Pin{} = Just $ Pin False+defaultAttributeValue QuadTree{} = Just $ QuadTree NormalQT+defaultAttributeValue Quantum{} = Just $ Quantum 0+defaultAttributeValue RankDir{} = Just $ RankDir FromTop+defaultAttributeValue Regular{} = Just $ Regular False+defaultAttributeValue ReMinCross{} = Just $ ReMinCross False+defaultAttributeValue RepulsiveForce{} = Just $ RepulsiveForce 1.0+defaultAttributeValue Root{} = Just $ Root (NodeName "")+defaultAttributeValue Rotate{} = Just $ Rotate 0+defaultAttributeValue Rotation{} = Just $ Rotation 0+defaultAttributeValue SameHead{} = Just $ SameHead ""+defaultAttributeValue SameTail{} = Just $ SameTail ""+defaultAttributeValue SearchSize{} = Just $ SearchSize 30+defaultAttributeValue Sep{} = Just $ Sep (DVal 4)+defaultAttributeValue Shape{} = Just $ Shape Ellipse+defaultAttributeValue ShowBoxes{} = Just $ ShowBoxes 0+defaultAttributeValue Sides{} = Just $ Sides 4+defaultAttributeValue Skew{} = Just $ Skew 0.0+defaultAttributeValue Smoothing{} = Just $ Smoothing NoSmooth+defaultAttributeValue SortV{} = Just $ SortV 0+defaultAttributeValue StyleSheet{} = Just $ StyleSheet ""+defaultAttributeValue TailURL{} = Just $ TailURL ""+defaultAttributeValue TailClip{} = Just $ TailClip True+defaultAttributeValue TailLabel{} = Just $ TailLabel (StrLabel "")+defaultAttributeValue TailPort{} = Just $ TailPort (CompassPoint CenterPoint)+defaultAttributeValue TailTarget{} = Just $ TailTarget ""+defaultAttributeValue TailTooltip{} = Just $ TailTooltip ""+defaultAttributeValue Target{} = Just $ Target ""+defaultAttributeValue Tooltip{} = Just $ Tooltip ""+defaultAttributeValue VoroMargin{} = Just $ VoroMargin 0.05+defaultAttributeValue Weight{} = Just $ Weight (Int 1)+defaultAttributeValue Width{} = Just $ Width 0.75+defaultAttributeValue XLabel{} = Just $ XLabel (StrLabel "")+defaultAttributeValue _ = Nothing++-- | Determine if the provided 'Text' value is a valid name for an 'UnknownAttribute'.+validUnknown :: AttributeName -> Bool+validUnknown txt = T.toLower txt `S.notMember` names+ && isIDString txt+ where+ names = (S.fromList . map T.toLower+ $ [ "Damping"+ , "K"+ , "URL"+ , "href"+ , "area"+ , "arrowhead"+ , "arrowsize"+ , "arrowtail"+ , "_background"+ , "bb"+ , "bgcolor"+ , "center"+ , "clusterrank"+ , "color"+ , "colorscheme"+ , "comment"+ , "compound"+ , "concentrate"+ , "constraint"+ , "decorate"+ , "defaultdist"+ , "dim"+ , "dimen"+ , "dir"+ , "diredgeconstraints"+ , "distortion"+ , "dpi"+ , "resolution"+ , "edgeURL"+ , "edgehref"+ , "edgetarget"+ , "edgetooltip"+ , "epsilon"+ , "esep"+ , "fillcolor"+ , "fixedsize"+ , "fontcolor"+ , "fontname"+ , "fontnames"+ , "fontpath"+ , "fontsize"+ , "forcelabels"+ , "gradientangle"+ , "group"+ , "headURL"+ , "headhref"+ , "head_lp"+ , "headclip"+ , "headlabel"+ , "headport"+ , "headtarget"+ , "headtooltip"+ , "height"+ , "id"+ , "image"+ , "imagepath"+ , "imagescale"+ , "inputscale"+ , "label"+ , "labelURL"+ , "labelhref"+ , "label_scheme"+ , "labelangle"+ , "labeldistance"+ , "labelfloat"+ , "labelfontcolor"+ , "labelfontname"+ , "labelfontsize"+ , "labeljust"+ , "labelloc"+ , "labeltarget"+ , "labeltooltip"+ , "landscape"+ , "layer"+ , "layerlistsep"+ , "layers"+ , "layerselect"+ , "layersep"+ , "layout"+ , "len"+ , "levels"+ , "levelsgap"+ , "lhead"+ , "LHeight"+ , "lp"+ , "ltail"+ , "lwidth"+ , "margin"+ , "maxiter"+ , "mclimit"+ , "mindist"+ , "minlen"+ , "mode"+ , "model"+ , "mosek"+ , "nodesep"+ , "nojustify"+ , "normalize"+ , "nslimit"+ , "nslimit1"+ , "ordering"+ , "orientation"+ , "outputorder"+ , "overlap"+ , "overlap_scaling"+ , "overlap_shrink"+ , "pack"+ , "packmode"+ , "pad"+ , "page"+ , "pagedir"+ , "pencolor"+ , "penwidth"+ , "peripheries"+ , "pin"+ , "pos"+ , "quadtree"+ , "quantum"+ , "rank"+ , "rankdir"+ , "ranksep"+ , "ratio"+ , "rects"+ , "regular"+ , "remincross"+ , "repulsiveforce"+ , "root"+ , "rotate"+ , "rotation"+ , "samehead"+ , "sametail"+ , "samplepoints"+ , "scale"+ , "searchsize"+ , "sep"+ , "shape"+ , "showboxes"+ , "sides"+ , "size"+ , "skew"+ , "smoothing"+ , "sortv"+ , "splines"+ , "start"+ , "style"+ , "stylesheet"+ , "tailURL"+ , "tailhref"+ , "tail_lp"+ , "tailclip"+ , "taillabel"+ , "tailport"+ , "tailtarget"+ , "tailtooltip"+ , "target"+ , "tooltip"+ , "truecolor"+ , "vertices"+ , "viewport"+ , "voro_margin"+ , "weight"+ , "width"+ , "xdotversion"+ , "xlabel"+ , "xlp"+ , "charset" -- Defined upstream, just not used here.+ ])+ `S.union`+ keywords+{- Delete to here -}++-- | Remove attributes that we don't want to consider:+--+-- * Those that are defaults+-- * colorscheme (as the colors embed it anyway)+rmUnwantedAttributes :: Attributes -> Attributes+rmUnwantedAttributes = filter (not . (`any` tests) . flip ($))+ where+ tests = [isDefault, isColorScheme]++ isDefault a = maybe False (a==) $ defaultAttributeValue a++ isColorScheme ColorScheme{} = True+ isColorScheme _ = False++-- -----------------------------------------------------------------------------+-- These parsing combinators are defined here for customisation purposes.++parseField :: (ParseDot a) => (a -> Attribute) -> String+ -> [(String, Parse Attribute)]+parseField c fld = [(fld, liftEqParse fld c)]++parseFields :: (ParseDot a) => (a -> Attribute) -> [String]+ -> [(String, Parse Attribute)]+parseFields c = concatMap (parseField c)++parseFieldBool :: (Bool -> Attribute) -> String -> [(String, Parse Attribute)]+parseFieldBool = (`parseFieldDef` True)++-- | For 'Bool'-like data structures where the presence of the field+-- name without a value implies a default value.+parseFieldDef :: (ParseDot a) => (a -> Attribute) -> a -> String+ -> [(String, Parse Attribute)]+parseFieldDef c d fld = [(fld, p)]+ where+ p = liftEqParse fld c+ `onFail`+ do nxt <- optional $ satisfy restIDString+ bool (fail "Not actually the field you were after")+ (return $ c d)+ (isNothing nxt)++-- | Attempt to parse the @\"=value\"@ part of a @key=value@ pair. If+-- there is an equal sign but the @value@ part doesn't parse, throw+-- an un-recoverable error.+liftEqParse :: (ParseDot a) => String -> (a -> Attribute) -> Parse Attribute+liftEqParse k c = do pStrict <- getsGS parseStrictly+ let adjErr = bool adjustErr adjustErrBad pStrict+ parseEq+ *> ( hasDef (fmap c parse)+ `adjErr`+ (("Unable to parse key=value with key of " ++ k+ ++ "\n\t") ++)+ )+ where+ hasDef p = maybe p (onFail p . (`stringRep` "\"\""))+ . defaultAttributeValue $ c undefined++-- -----------------------------------------------------------------------------++{- | If performing any custom pre-/post-processing on Dot code, you+ may wish to utilise some custom 'Attributes'. These are wrappers+ around the 'UnknownAttribute' constructor (and thus 'CustomAttribute'+ is just an alias for 'Attribute').++ You should ensure that 'validUnknown' is 'True' for any potential+ custom attribute name.++-}+type CustomAttribute = Attribute++-- | Create a custom attribute.+customAttribute :: AttributeName -> Text -> CustomAttribute+customAttribute = UnknownAttribute++-- | Determines whether or not this is a custom attribute.+isCustom :: Attribute -> Bool+isCustom UnknownAttribute{} = True+isCustom _ = False++isSpecifiedCustom :: AttributeName -> Attribute -> Bool+isSpecifiedCustom nm (UnknownAttribute nm' _) = nm == nm'+isSpecifiedCustom _ _ = False++-- | The value of a custom attribute. Will throw a+-- 'GraphvizException' if the provided 'Attribute' isn't a custom+-- one.+customValue :: CustomAttribute -> Text+customValue (UnknownAttribute _ v) = v+customValue attr = throw . NotCustomAttr . T.unpack+ $ printIt attr++-- | The name of a custom attribute. Will throw a+-- 'GraphvizException' if the provided 'Attribute' isn't a custom+-- one.+customName :: CustomAttribute -> AttributeName+customName (UnknownAttribute nm _) = nm+customName attr = throw . NotCustomAttr . T.unpack+ $ printIt attr++-- | Returns all custom attributes and the list of non-custom Attributes.+findCustoms :: Attributes -> ([CustomAttribute], Attributes)+findCustoms = partition isCustom++-- | Find the (first instance of the) specified custom attribute and+-- returns it along with all other Attributes.+findSpecifiedCustom :: AttributeName -> Attributes+ -> Maybe (CustomAttribute, Attributes)+findSpecifiedCustom nm attrs+ = case break (isSpecifiedCustom nm) attrs of+ (bf,cust:aft) -> Just (cust, bf ++ aft)+ _ -> Nothing++-- | Delete all custom attributes (actually, this will delete all+-- 'UnknownAttribute' values; as such it can also be used to remove+-- legacy attributes).+deleteCustomAttributes :: Attributes -> Attributes+deleteCustomAttributes = filter (not . isCustom)++-- | Removes all instances of the specified custom attribute.+deleteSpecifiedCustom :: AttributeName -> Attributes -> Attributes+deleteSpecifiedCustom nm = filter (not . isSpecifiedCustom nm)
Data/GraphViz/Attributes/HTML.hs view
@@ -67,20 +67,20 @@ , Scale(..) ) where -import Data.GraphViz.Parsing-import Data.GraphViz.Printing import Data.GraphViz.Attributes.Colors import Data.GraphViz.Attributes.Internal-import Data.GraphViz.Util(bool)+import Data.GraphViz.Internal.Util (bool)+import Data.GraphViz.Parsing+import Data.GraphViz.Printing -import Numeric(readHex)-import Data.Char(chr, ord, isSpace)-import Data.Function(on)-import Data.List(delete)-import Data.Maybe(catMaybes, listToMaybe)-import Data.Word(Word8, Word16)-import qualified Data.Map as Map+import Data.Char (chr, isSpace, ord)+import Data.Function (on)+import Data.List (delete)+import qualified Data.Map as Map+import Data.Maybe (catMaybes, listToMaybe) import qualified Data.Text.Lazy as T+import Data.Word (Word16, Word8)+import Numeric (readHex) -- ----------------------------------------------------------------------------- @@ -154,11 +154,11 @@ parseList = parseUnqtList data Format = Italics- | Bold- | Underline- | Subscript- | Superscript- deriving (Eq, Ord, Bounded, Enum, Show, Read)+ | Bold+ | Underline+ | Subscript+ | Superscript+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot Format where unqtDot Italics = text "I"@@ -263,7 +263,7 @@ instance ParseDot Cell where parseUnqt = oneOf [ parseCell LabelCell parse- , parseCell ImgCell $ wrapWhitespace parseUnqt+ , parseCell ImgCell $ wrapWhitespace parse , parseEmptyTag (const VerticalRule) "VR" ] `adjustErr`@@ -412,6 +412,8 @@ ) -- Can't use liftEqParse, etc. here because it causes backtracking -- problems when the attributes could apply to multiple constructors.+-- This includes using commit! (Example: if it starts with a FONT tag,+-- is it a Table or Text? -- | Specifies horizontal placement. When an object is allocated more -- space than required, this value determines where the extra space
Data/GraphViz/Attributes/Internal.hs view
@@ -9,7 +9,8 @@ Maintainer : Ivan.Miljenovic@gmail.com This module is defined so as to avoid exposing internal functions- in the external API.+ in the external API. These are those that are needed for the+ testsuite. -} @@ -24,10 +25,10 @@ import Data.GraphViz.Parsing import Data.GraphViz.Printing -import Data.Maybe(isNothing)-import qualified Data.Map as Map-import Data.Map(Map)-import Data.Text.Lazy(Text)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe (isNothing)+import Data.Text.Lazy (Text) -- -----------------------------------------------------------------------------
+ Data/GraphViz/Attributes/Values.hs view
@@ -0,0 +1,1631 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}+{- |+ Module : Data.GraphViz.Attributes.Values+ Description : Values for use with the Attribute data type+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ Defined to have smaller modules and thus faster compilation times.++ -}+module Data.GraphViz.Attributes.Values where++import qualified Data.GraphViz.Attributes.HTML as Html+import Data.GraphViz.Attributes.Internal+import Data.GraphViz.Internal.State (getLayerListSep,+ getLayerSep,+ setLayerListSep,+ setLayerSep)+import Data.GraphViz.Internal.Util (bool, stringToInt)+import Data.GraphViz.Parsing+import Data.GraphViz.Printing++import Data.List (intercalate)+import Data.Maybe (isJust)+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Data.Word (Word16)+import System.FilePath (searchPathSeparator, splitSearchPath)++-- -----------------------------------------------------------------------------++{- |++ Some 'Attribute's (mainly label-like ones) take a 'String' argument+ that allows for extra escape codes. This library doesn't do any+ extra checks or special parsing for these escape codes, but usage+ of 'EscString' rather than 'Text' indicates that the Graphviz+ tools will recognise these extra escape codes for these+ 'Attribute's.++ The extra escape codes include (note that these are all Strings):++ [@\\N@] Replace with the name of the node (for Node 'Attribute's).++ [@\\G@] Replace with the name of the graph (for Node 'Attribute's)+ or the name of the graph or cluster, whichever is+ applicable (for Graph, Cluster and Edge 'Attribute's).++ [@\\E@] Replace with the name of the edge, formed by the two+ adjoining nodes and the edge type (for Edge 'Attribute's).++ [@\\T@] Replace with the name of the tail node (for Edge+ 'Attribute's).++ [@\\H@] Replace with the name of the head node (for Edge+ 'Attribute's).++ [@\\L@] Replace with the object's label (for all 'Attribute's).++ Also, if the 'Attribute' in question is 'Label', 'HeadLabel' or+ 'TailLabel', then @\\n@, @\\l@ and @\\r@ split the label into lines+ centered, left-justified and right-justified respectively.++ -}+type EscString = Text++-- -----------------------------------------------------------------------------++-- | Should only have 2D points (i.e. created with 'createPoint').+data Rect = Rect Point Point+ deriving (Eq, Ord, Show, Read)++instance PrintDot Rect where+ unqtDot (Rect p1 p2) = printPoint2DUnqt p1 <> comma <> printPoint2DUnqt p2++ toDot = dquotes . unqtDot++ unqtListToDot = hsep . mapM unqtDot++instance ParseDot Rect where+ parseUnqt = uncurry Rect <$> commaSep' parsePoint2D parsePoint2D++ parse = quotedParse parseUnqt++ parseUnqtList = sepBy1 parseUnqt whitespace1++-- -----------------------------------------------------------------------------++-- | If 'Local', then sub-graphs that are clusters are given special+-- treatment. 'Global' and 'NoCluster' currently appear to be+-- identical and turn off the special cluster processing.+data ClusterMode = Local+ | Global+ | NoCluster+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot ClusterMode where+ unqtDot Local = text "local"+ unqtDot Global = text "global"+ unqtDot NoCluster = text "none"++instance ParseDot ClusterMode where+ parseUnqt = oneOf [ stringRep Local "local"+ , stringRep Global "global"+ , stringRep NoCluster "none"+ ]++-- -----------------------------------------------------------------------------++-- | Specify where to place arrow heads on an edge.+data DirType = Forward -- ^ Draw a directed edge with an arrow to the+ -- node it's pointing go.+ | Back -- ^ Draw a reverse directed edge with an arrow+ -- to the node it's coming from.+ | Both -- ^ Draw arrows on both ends of the edge.+ | NoDir -- ^ Draw an undirected edge.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot DirType where+ unqtDot Forward = text "forward"+ unqtDot Back = text "back"+ unqtDot Both = text "both"+ unqtDot NoDir = text "none"++instance ParseDot DirType where+ parseUnqt = oneOf [ stringRep Forward "forward"+ , stringRep Back "back"+ , stringRep Both "both"+ , stringRep NoDir "none"+ ]++-- -----------------------------------------------------------------------------++-- | Only when @mode == 'IpSep'@.+data DEConstraints = EdgeConstraints+ | NoConstraints+ | HierConstraints+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot DEConstraints where+ unqtDot EdgeConstraints = unqtDot True+ unqtDot NoConstraints = unqtDot False+ unqtDot HierConstraints = text "hier"++instance ParseDot DEConstraints where+ parseUnqt = fmap (bool NoConstraints EdgeConstraints) parse+ `onFail`+ stringRep HierConstraints "hier"++-- -----------------------------------------------------------------------------++-- | Either a 'Double' or a (2D) 'Point' (i.e. created with+-- 'createPoint').+--+-- Whilst it is possible to create a 'Point' value with either a+-- third co-ordinate or a forced position, these are ignored for+-- printing/parsing.+--+-- An optional prefix of @\'+\'@ is allowed when parsing.+data DPoint = DVal Double+ | PVal Point+ deriving (Eq, Ord, Show, Read)++instance PrintDot DPoint where+ unqtDot (DVal d) = unqtDot d+ unqtDot (PVal p) = printPoint2DUnqt p++ toDot (DVal d) = toDot d+ toDot (PVal p) = printPoint2D p++instance ParseDot DPoint where+ parseUnqt = optional (character '+')+ *> oneOf [ PVal <$> parsePoint2D+ , DVal <$> parseUnqt+ ]++ parse = quotedParse parseUnqt -- A `+' would need to be quoted.+ `onFail`+ fmap DVal (parseSignedFloat False) -- Don't use parseUnqt!++-- -----------------------------------------------------------------------------++-- | The mapping used for 'FontName' values in SVG output.+--+-- More information can be found at <http://www.graphviz.org/doc/fontfaq.txt>.+data SVGFontNames = SvgNames -- ^ Use the legal generic SVG font names.+ | PostScriptNames -- ^ Use PostScript font names.+ | FontConfigNames -- ^ Use fontconfig font conventions.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot SVGFontNames where+ unqtDot SvgNames = text "svg"+ unqtDot PostScriptNames = text "ps"+ unqtDot FontConfigNames = text "gd"++instance ParseDot SVGFontNames where+ parseUnqt = oneOf [ stringRep SvgNames "svg"+ , stringRep PostScriptNames "ps"+ , stringRep FontConfigNames "gd"+ ]++ parse = stringRep SvgNames "\"\""+ `onFail`+ optionalQuoted parseUnqt++-- -----------------------------------------------------------------------------++-- | Maximum width and height of drawing in inches.+data GraphSize = GSize { width :: Double+ -- | If @Nothing@, then the height is the+ -- same as the width.+ , height :: Maybe Double+ -- | If drawing is smaller than specified+ -- size, this value determines whether it+ -- is scaled up.+ , desiredSize :: Bool+ }+ deriving (Eq, Ord, Show, Read)++instance PrintDot GraphSize where+ unqtDot (GSize w mh ds) = bool id (<> char '!') ds+ . maybe id (\h -> (<> unqtDot h) . (<> comma)) mh+ $ unqtDot w++ toDot (GSize w Nothing False) = toDot w+ toDot gs = dquotes $ unqtDot gs++instance ParseDot GraphSize where+ parseUnqt = GSize <$> parseUnqt+ <*> optional (parseComma *> whitespace *> parseUnqt)+ <*> (isJust <$> optional (character '!'))++ parse = quotedParse parseUnqt+ `onFail`+ fmap (\ w -> GSize w Nothing False) (parseSignedFloat False)++-- -----------------------------------------------------------------------------++-- | For 'Neato' unless indicated otherwise.+data ModeType = Major+ | KK+ | Hier+ | IpSep+ | SpringMode -- ^ For 'Sfdp', requires Graphviz >= 2.32.0.+ | MaxEnt -- ^ For 'Sfdp', requires Graphviz >= 2.32.0.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot ModeType where+ unqtDot Major = text "major"+ unqtDot KK = text "KK"+ unqtDot Hier = text "hier"+ unqtDot IpSep = text "ipsep"+ unqtDot SpringMode = text "spring"+ unqtDot MaxEnt = text "maxent"++instance ParseDot ModeType where+ parseUnqt = oneOf [ stringRep Major "major"+ , stringRep KK "KK"+ , stringRep Hier "hier"+ , stringRep IpSep "ipsep"+ , stringRep SpringMode "spring"+ , stringRep MaxEnt "maxent"+ ]++-- -----------------------------------------------------------------------------++data Model = ShortPath+ | SubSet+ | Circuit+ | MDS+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot Model where+ unqtDot ShortPath = text "shortpath"+ unqtDot SubSet = text "subset"+ unqtDot Circuit = text "circuit"+ unqtDot MDS = text "mds"++instance ParseDot Model where+ parseUnqt = oneOf [ stringRep ShortPath "shortpath"+ , stringRep SubSet "subset"+ , stringRep Circuit "circuit"+ , stringRep MDS "mds"+ ]++-- -----------------------------------------------------------------------------++data Label = StrLabel EscString+ | HtmlLabel Html.Label -- ^ If 'PlainText' is used, the+ -- 'Html.Label' value is the entire+ -- \"shape\"; if anything else+ -- except 'PointShape' is used then+ -- the 'Html.Label' is embedded+ -- within the shape.+ | RecordLabel RecordFields -- ^ For nodes only; requires+ -- either 'Record' or+ -- 'MRecord' as the shape.+ deriving (Eq, Ord, Show, Read)++instance PrintDot Label where+ unqtDot (StrLabel s) = unqtDot s+ unqtDot (HtmlLabel h) = angled $ unqtDot h+ unqtDot (RecordLabel fs) = unqtDot fs++ toDot (StrLabel s) = toDot s+ toDot h@HtmlLabel{} = unqtDot h+ toDot (RecordLabel fs) = toDot fs++instance ParseDot Label where+ -- Don't have to worry about being able to tell the difference+ -- between an HtmlLabel and a RecordLabel starting with a PortPos,+ -- since the latter will be in quotes and the former won't.++ parseUnqt = oneOf [ HtmlLabel <$> parseAngled parseUnqt+ , RecordLabel <$> parseUnqt+ , StrLabel <$> parseUnqt+ ]++ parse = oneOf [ HtmlLabel <$> parseAngled parse+ , RecordLabel <$> parse+ , StrLabel <$> parse+ ]++-- -----------------------------------------------------------------------------++-- | A RecordFields value should never be empty.+type RecordFields = [RecordField]++-- | Specifies the sub-values of a record-based label. By default,+-- the cells are laid out horizontally; use 'FlipFields' to change+-- the orientation of the fields (can be applied recursively). To+-- change the default orientation, use 'RankDir'.+data RecordField = LabelledTarget PortName EscString+ | PortName PortName -- ^ Will result in no label for+ -- that cell.+ | FieldLabel EscString+ | FlipFields RecordFields+ deriving (Eq, Ord, Show, Read)++instance PrintDot RecordField where+ -- Have to use 'printPortName' to add the @\'<\'@ and @\'>\'@.+ unqtDot (LabelledTarget t s) = printPortName t <+> unqtRecordString s+ unqtDot (PortName t) = printPortName t+ unqtDot (FieldLabel s) = unqtRecordString s+ unqtDot (FlipFields rs) = braces $ unqtDot rs++ toDot (FieldLabel s) = printEscaped recordEscChars s+ toDot rf = dquotes $ unqtDot rf++ unqtListToDot [f] = unqtDot f+ unqtListToDot fs = hcat . punctuate (char '|') $ mapM unqtDot fs++ listToDot [f] = toDot f+ listToDot fs = dquotes $ unqtListToDot fs++instance ParseDot RecordField where+ parseUnqt = (liftA2 maybe PortName LabelledTarget+ <$> (PN <$> parseAngled parseRecord)+ <*> optional (whitespace1 *> parseRecord)+ )+ `onFail`+ fmap FieldLabel parseRecord+ `onFail`+ fmap FlipFields (parseBraced parseUnqt)+ `onFail`+ fail "Unable to parse RecordField"++ parse = quotedParse parseUnqt++ parseUnqtList = wrapWhitespace $ sepBy1 parseUnqt (wrapWhitespace $ character '|')++ -- Note: a singleton unquoted 'FieldLabel' is /not/ valid, as it+ -- will cause parsing problems for other 'Label' types.+ parseList = do rfs <- quotedParse parseUnqtList+ if validRFs rfs+ then return rfs+ else fail "This is a StrLabel, not a RecordLabel"+ where+ validRFs [FieldLabel str] = T.any (`elem` recordEscChars) str+ validRFs _ = True++-- | Print a 'PortName' value as expected within a Record data+-- structure.+printPortName :: PortName -> DotCode+printPortName = angled . unqtRecordString . portName++parseRecord :: Parse Text+parseRecord = parseEscaped False recordEscChars []++unqtRecordString :: Text -> DotCode+unqtRecordString = unqtEscaped recordEscChars++recordEscChars :: [Char]+recordEscChars = ['{', '}', '|', ' ', '<', '>']++-- -----------------------------------------------------------------------------++-- | How to treat a node whose name is of the form \"@|edgelabel|*@\"+-- as a special node representing an edge label.+data LabelScheme = NotEdgeLabel -- ^ No effect+ | CloseToCenter -- ^ Make node close to center of neighbor+ | CloseToOldCenter -- ^ Make node close to old center of neighbor+ | RemoveAndStraighten -- ^ Use a two-step process.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot LabelScheme where+ unqtDot NotEdgeLabel = int 0+ unqtDot CloseToCenter = int 1+ unqtDot CloseToOldCenter = int 2+ unqtDot RemoveAndStraighten = int 3++instance ParseDot LabelScheme where+ -- Use string-based parsing rather than parsing an integer just to make it easier+ parseUnqt = stringValue [ ("0", NotEdgeLabel)+ , ("1", CloseToCenter)+ , ("2", CloseToOldCenter)+ , ("3", RemoveAndStraighten)+ ]++-- -----------------------------------------------------------------------------++data Point = Point { xCoord :: Double+ , yCoord :: Double+ -- | Can only be 'Just' for @'Dim' 3@ or greater.+ , zCoord :: Maybe Double+ -- | Input to Graphviz only: specify that the+ -- node position should not change.+ , forcePos :: Bool+ }+ deriving (Eq, Ord, Show, Read)++-- | Create a point with only @x@ and @y@ values.+createPoint :: Double -> Double -> Point+createPoint x y = Point x y Nothing False++printPoint2DUnqt :: Point -> DotCode+printPoint2DUnqt p = commaDel (xCoord p) (yCoord p)++printPoint2D :: Point -> DotCode+printPoint2D = dquotes . printPoint2DUnqt++parsePoint2D :: Parse Point+parsePoint2D = uncurry createPoint <$> commaSepUnqt++instance PrintDot Point where+ unqtDot (Point x y mz frs) = bool id (<> char '!') frs+ . maybe id (\ z -> (<> unqtDot z) . (<> comma)) mz+ $ commaDel x y++ toDot = dquotes . unqtDot++ unqtListToDot = hsep . mapM unqtDot++ listToDot = dquotes . unqtListToDot++instance ParseDot Point where+ parseUnqt = uncurry Point+ <$> commaSepUnqt+ <*> optional (parseComma *> parseUnqt)+ <*> (isJust <$> optional (character '!'))++ parse = quotedParse parseUnqt++ parseUnqtList = sepBy1 parseUnqt whitespace1++-- -----------------------------------------------------------------------------++-- | How to deal with node overlaps.+--+-- Defaults to 'KeepOverlaps' /except/ for 'Fdp' and 'Sfdp'.+--+-- The ability to specify the number of tries for 'Fdp''s initial+-- force-directed technique is /not/ supported (by default, 'Fdp' uses+-- @9@ passes of its in-built technique, and then @'PrismOverlap'+-- Nothing@).+--+-- For 'Sfdp', the default is @'PrismOverlap' (Just 0)@.+data Overlap = KeepOverlaps+ | ScaleOverlaps -- ^ Remove overlaps by uniformly scaling in x and y.+ | ScaleXYOverlaps -- ^ Remove overlaps by separately scaling x and y.+ | PrismOverlap (Maybe Word16) -- ^ Requires the Prism+ -- library to be+ -- available (if not,+ -- this is equivalent to+ -- 'VoronoiOverlap'). @'Nothing'@+ -- is equivalent to+ -- @'Just' 1000@.+ -- Influenced by+ -- 'OverlapScaling'.+ | VoronoiOverlap -- ^ Requires Graphviz >= 2.30.0.+ | CompressOverlap -- ^ Scale layout down as much as+ -- possible without introducing+ -- overlaps, assuming none to begin+ -- with.+ | VpscOverlap -- ^ Uses quadratic optimization to+ -- minimize node displacement.+ | IpsepOverlap -- ^ Only when @mode == 'IpSep'@+ deriving (Eq, Ord, Show, Read)++instance PrintDot Overlap where+ unqtDot KeepOverlaps = unqtDot True+ unqtDot ScaleOverlaps = text "scale"+ unqtDot ScaleXYOverlaps = text "scalexy"+ unqtDot (PrismOverlap i) = maybe id (flip (<>) . unqtDot) i $ text "prism"+ unqtDot VoronoiOverlap = text "voronoi"+ unqtDot CompressOverlap = text "compress"+ unqtDot VpscOverlap = text "vpsc"+ unqtDot IpsepOverlap = text "ipsep"++-- | Note that @overlap=false@ defaults to @'PrismOverlap' Nothing@,+-- but if the Prism library isn't available then it is equivalent to+-- 'VoronoiOverlap'.+instance ParseDot Overlap where+ parseUnqt = oneOf [ stringRep KeepOverlaps "true"+ , stringRep ScaleXYOverlaps "scalexy"+ , stringRep ScaleOverlaps "scale"+ , string "prism" *> fmap PrismOverlap (optional parse)+ , stringRep (PrismOverlap Nothing) "false"+ , stringRep VoronoiOverlap "voronoi"+ , stringRep CompressOverlap "compress"+ , stringRep VpscOverlap "vpsc"+ , stringRep IpsepOverlap "ipsep"+ ]++-- -----------------------------------------------------------------------------++newtype LayerSep = LSep Text+ deriving (Eq, Ord, Show, Read)++instance PrintDot LayerSep where+ unqtDot (LSep ls) = setLayerSep (T.unpack ls) *> unqtDot ls++ toDot (LSep ls) = setLayerSep (T.unpack ls) *> toDot ls++instance ParseDot LayerSep where+ parseUnqt = do ls <- parseUnqt+ setLayerSep $ T.unpack ls+ return $ LSep ls++ parse = do ls <- parse+ setLayerSep $ T.unpack ls+ return $ LSep ls++newtype LayerListSep = LLSep Text+ deriving (Eq, Ord, Show, Read)++instance PrintDot LayerListSep where+ unqtDot (LLSep ls) = setLayerListSep (T.unpack ls) *> unqtDot ls++ toDot (LLSep ls) = setLayerListSep (T.unpack ls) *> toDot ls++instance ParseDot LayerListSep where+ parseUnqt = do ls <- parseUnqt+ setLayerListSep $ T.unpack ls+ return $ LLSep ls++ parse = do ls <- parse+ setLayerListSep $ T.unpack ls+ return $ LLSep ls++type LayerRange = [LayerRangeElem]++data LayerRangeElem = LRID LayerID+ | LRS LayerID LayerID+ deriving (Eq, Ord, Show, Read)++instance PrintDot LayerRangeElem where+ unqtDot (LRID lid) = unqtDot lid+ unqtDot (LRS id1 id2) = do ls <- getLayerSep+ let s = unqtDot $ head ls+ unqtDot id1 <> s <> unqtDot id2++ toDot (LRID lid) = toDot lid+ toDot lrs = dquotes $ unqtDot lrs++ unqtListToDot lr = do lls <- getLayerListSep+ let s = unqtDot $ head lls+ hcat . punctuate s $ mapM unqtDot lr++ listToDot [lre] = toDot lre+ listToDot lrs = dquotes $ unqtListToDot lrs++instance ParseDot LayerRangeElem where+ parseUnqt = ignoreSep LRS parseUnqt parseLayerSep parseUnqt+ `onFail`+ fmap LRID parseUnqt++ parse = quotedParse (ignoreSep LRS parseUnqt parseLayerSep parseUnqt)+ `onFail`+ fmap LRID parse++ parseUnqtList = sepBy parseUnqt parseLayerListSep++ parseList = quotedParse parseUnqtList+ `onFail`+ fmap ((:[]) . LRID) parse++parseLayerSep :: Parse ()+parseLayerSep = do ls <- getLayerSep+ many1Satisfy (`elem` ls) *> return ()++parseLayerName :: Parse Text+parseLayerName = parseEscaped False [] =<< liftA2 (++) getLayerSep getLayerListSep++parseLayerName' :: Parse Text+parseLayerName' = stringBlock+ `onFail`+ quotedParse parseLayerName++parseLayerListSep :: Parse ()+parseLayerListSep = do lls <- getLayerListSep+ many1Satisfy (`elem` lls) *> return ()++-- | You should not have any layer separator characters for the+-- 'LRName' option, as they won't be parseable.+data LayerID = AllLayers+ | LRInt Int+ | LRName Text -- ^ Should not be a number or @"all"@.+ deriving (Eq, Ord, Show, Read)++instance PrintDot LayerID where+ unqtDot AllLayers = text "all"+ unqtDot (LRInt n) = unqtDot n+ unqtDot (LRName nm) = unqtDot nm++ toDot (LRName nm) = toDot nm+ -- Other two don't need quotes+ toDot li = unqtDot li++ unqtListToDot ll = do ls <- getLayerSep+ let s = unqtDot $ head ls+ hcat . punctuate s $ mapM unqtDot ll++ listToDot [l] = toDot l+ -- Might not need quotes, but probably will. Can't tell either+ -- way since we don't know what the separator character will be.+ listToDot ll = dquotes $ unqtDot ll++instance ParseDot LayerID where+ parseUnqt = checkLayerName <$> parseLayerName -- tests for Int and All++ parse = oneOf [ checkLayerName <$> parseLayerName'+ , LRInt <$> parse -- Mainly for unquoted case.+ ]++checkLayerName :: Text -> LayerID+checkLayerName str = maybe checkAll LRInt $ stringToInt str+ where+ checkAll = if T.toLower str == "all"+ then AllLayers+ else LRName str++-- Remember: this /must/ be a newtype as we can't use arbitrary+-- LayerID values!++-- | A list of layer names. The names should all be unique 'LRName'+-- values, and when printed will use an arbitrary character from+-- 'defLayerSep'. The values in the list are implicitly numbered+-- @1, 2, ...@.+newtype LayerList = LL [LayerID]+ deriving (Eq, Ord, Show, Read)++instance PrintDot LayerList where+ unqtDot (LL ll) = unqtDot ll++ toDot (LL ll) = toDot ll++instance ParseDot LayerList where+ parseUnqt = LL <$> sepBy1 parseUnqt parseLayerSep++ parse = quotedParse parseUnqt+ `onFail`+ fmap (LL . (:[]) . LRName) stringBlock+ `onFail`+ quotedParse (stringRep (LL []) "")++-- -----------------------------------------------------------------------------++data Order = OutEdges -- ^ Draw outgoing edges in order specified.+ | InEdges -- ^ Draw incoming edges in order specified.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot Order where+ unqtDot OutEdges = text "out"+ unqtDot InEdges = text "in"++instance ParseDot Order where+ parseUnqt = oneOf [ stringRep OutEdges "out"+ , stringRep InEdges "in"+ ]++-- -----------------------------------------------------------------------------++data OutputMode = BreadthFirst | NodesFirst | EdgesFirst+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot OutputMode where+ unqtDot BreadthFirst = text "breadthfirst"+ unqtDot NodesFirst = text "nodesfirst"+ unqtDot EdgesFirst = text "edgesfirst"++instance ParseDot OutputMode where+ parseUnqt = oneOf [ stringRep BreadthFirst "breadthfirst"+ , stringRep NodesFirst "nodesfirst"+ , stringRep EdgesFirst "edgesfirst"+ ]++-- -----------------------------------------------------------------------------++data Pack = DoPack+ | DontPack+ | PackMargin Int -- ^ If non-negative, then packs; otherwise doesn't.+ deriving (Eq, Ord, Show, Read)++instance PrintDot Pack where+ unqtDot DoPack = unqtDot True+ unqtDot DontPack = unqtDot False+ unqtDot (PackMargin m) = unqtDot m++instance ParseDot Pack where+ -- What happens if it parses 0? It's non-negative, but parses as False+ parseUnqt = oneOf [ PackMargin <$> parseUnqt+ , bool DontPack DoPack <$> onlyBool+ ]++-- -----------------------------------------------------------------------------++data PackMode = PackNode+ | PackClust+ | PackGraph+ | PackArray Bool Bool (Maybe Int) -- ^ Sort by cols, sort+ -- by user, number of+ -- rows/cols+ deriving (Eq, Ord, Show, Read)++instance PrintDot PackMode where+ unqtDot PackNode = text "node"+ unqtDot PackClust = text "clust"+ unqtDot PackGraph = text "graph"+ unqtDot (PackArray c u mi) = addNum . isU . isC . isUnder+ $ text "array"+ where+ addNum = maybe id (flip (<>) . unqtDot) mi+ isUnder = if c || u+ then (<> char '_')+ else id+ isC = if c+ then (<> char 'c')+ else id+ isU = if u+ then (<> char 'u')+ else id++instance ParseDot PackMode where+ parseUnqt = oneOf [ stringRep PackNode "node"+ , stringRep PackClust "clust"+ , stringRep PackGraph "graph"+ , do string "array"+ mcu <- optional $ character '_' *> many1 (satisfy isCU)+ let c = hasCharacter mcu 'c'+ u = hasCharacter mcu 'u'+ mi <- optional parseUnqt+ return $ PackArray c u mi+ ]+ where+ hasCharacter ms c = maybe False (elem c) ms+ -- Also checks and removes quote characters+ isCU = (`elem` ['c', 'u'])++-- -----------------------------------------------------------------------------++data Pos = PointPos Point+ | SplinePos [Spline]+ deriving (Eq, Ord, Show, Read)++instance PrintDot Pos where+ unqtDot (PointPos p) = unqtDot p+ unqtDot (SplinePos ss) = unqtDot ss++ toDot (PointPos p) = toDot p+ toDot (SplinePos ss) = toDot ss++instance ParseDot Pos where+ -- Have to be careful with this: if we try to parse points first,+ -- then a spline with no start and end points will erroneously get+ -- parsed as a point and then the parser will crash as it expects a+ -- closing quote character...+ parseUnqt = do splns <- parseUnqt+ case splns of+ [Spline Nothing Nothing [p]] -> return $ PointPos p+ _ -> return $ SplinePos splns++ parse = quotedParse parseUnqt++-- -----------------------------------------------------------------------------++-- | Controls how (and if) edges are represented.+--+-- For 'Dot', the default is 'SplineEdges'; for all other layouts+-- the default is 'LineEdges'.+data EdgeType = SplineEdges -- ^ Except for 'Dot', requires+ -- non-overlapping nodes (see+ -- 'Overlap').+ | LineEdges+ | NoEdges+ | PolyLine+ | Ortho -- ^ Does not handle ports or edge labels in 'Dot'.+ | Curved -- ^ Requires Graphviz >= 2.30.0.+ | CompoundEdge -- ^ 'Fdp' only+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot EdgeType where+ unqtDot SplineEdges = text "spline"+ unqtDot LineEdges = text "line"+ unqtDot NoEdges = empty+ unqtDot PolyLine = text "polyline"+ unqtDot Ortho = text "ortho"+ unqtDot Curved = text "curved"+ unqtDot CompoundEdge = text "compound"++ toDot NoEdges = dquotes empty+ toDot et = unqtDot et++instance ParseDot EdgeType where+ -- Can't parse NoEdges without quotes.+ parseUnqt = oneOf [ bool LineEdges SplineEdges <$> parse+ , stringRep SplineEdges "spline"+ , stringRep LineEdges "line"+ , stringRep NoEdges "none"+ , stringRep PolyLine "polyline"+ , stringRep Ortho "ortho"+ , stringRep Curved "curved"+ , stringRep CompoundEdge "compound"+ ]++ parse = stringRep NoEdges "\"\""+ `onFail`+ optionalQuoted parseUnqt++-- -----------------------------------------------------------------------------++-- | Upper-case first character is major order;+-- lower-case second character is minor order.+data PageDir = Bl | Br | Tl | Tr | Rb | Rt | Lb | Lt+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot PageDir where+ unqtDot Bl = text "BL"+ unqtDot Br = text "BR"+ unqtDot Tl = text "TL"+ unqtDot Tr = text "TR"+ unqtDot Rb = text "RB"+ unqtDot Rt = text "RT"+ unqtDot Lb = text "LB"+ unqtDot Lt = text "LT"++instance ParseDot PageDir where+ parseUnqt = stringValue [ ("BL", Bl)+ , ("BR", Br)+ , ("TL", Tl)+ , ("TR", Tr)+ , ("RB", Rb)+ , ("RT", Rt)+ , ("LB", Lb)+ , ("LT", Lt)+ ]++-- -----------------------------------------------------------------------------++-- | The number of points in the list must be equivalent to 1 mod 3;+-- note that this is not checked.+data Spline = Spline { endPoint :: Maybe Point+ , startPoint :: Maybe Point+ , splinePoints :: [Point]+ }+ deriving (Eq, Ord, Show, Read)++instance PrintDot Spline where+ unqtDot (Spline me ms ps) = addE . addS+ . hsep+ $ mapM unqtDot ps+ where+ addP t = maybe id ((<+>) . commaDel t)+ addS = addP 's' ms+ addE = addP 'e' me++ toDot = dquotes . unqtDot++ unqtListToDot = hcat . punctuate semi . mapM unqtDot++ listToDot = dquotes . unqtListToDot++instance ParseDot Spline where+ parseUnqt = Spline <$> parseP 'e' <*> parseP 's'+ <*> sepBy1 parseUnqt whitespace1+ where+ parseP t = optional (character t *> parseComma *> parseUnqt <* whitespace1)++ parse = quotedParse parseUnqt++ parseUnqtList = sepBy1 parseUnqt (character ';')++-- -----------------------------------------------------------------------------++data QuadType = NormalQT+ | FastQT+ | NoQT+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot QuadType where+ unqtDot NormalQT = text "normal"+ unqtDot FastQT = text "fast"+ unqtDot NoQT = text "none"++instance ParseDot QuadType where+ -- Have to take into account the slightly different interpretation+ -- of Bool used as an option for parsing QuadType+ parseUnqt = oneOf [ stringRep NormalQT "normal"+ , stringRep FastQT "fast"+ , stringRep NoQT "none"+ , character '2' *> return FastQT -- weird bool+ , bool NoQT NormalQT <$> parse+ ]++-- -----------------------------------------------------------------------------++-- | Specify the root node either as a Node attribute or a Graph attribute.+data Root = IsCentral -- ^ For Nodes only+ | NotCentral -- ^ For Nodes only+ | NodeName Text -- ^ For Graphs only+ deriving (Eq, Ord, Show, Read)++instance PrintDot Root where+ unqtDot IsCentral = unqtDot True+ unqtDot NotCentral = unqtDot False+ unqtDot (NodeName n) = unqtDot n++ toDot (NodeName n) = toDot n+ toDot r = unqtDot r++instance ParseDot Root where+ parseUnqt = fmap (bool NotCentral IsCentral) onlyBool+ `onFail`+ fmap NodeName parseUnqt++ parse = optionalQuoted (bool NotCentral IsCentral <$> onlyBool)+ `onFail`+ fmap NodeName parse++-- -----------------------------------------------------------------------------++data RankType = SameRank+ | MinRank+ | SourceRank+ | MaxRank+ | SinkRank+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot RankType where+ unqtDot SameRank = text "same"+ unqtDot MinRank = text "min"+ unqtDot SourceRank = text "source"+ unqtDot MaxRank = text "max"+ unqtDot SinkRank = text "sink"++instance ParseDot RankType where+ parseUnqt = stringValue [ ("same", SameRank)+ , ("min", MinRank)+ , ("source", SourceRank)+ , ("max", MaxRank)+ , ("sink", SinkRank)+ ]++-- -----------------------------------------------------------------------------++data RankDir = FromTop+ | FromLeft+ | FromBottom+ | FromRight+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot RankDir where+ unqtDot FromTop = text "TB"+ unqtDot FromLeft = text "LR"+ unqtDot FromBottom = text "BT"+ unqtDot FromRight = text "RL"++instance ParseDot RankDir where+ parseUnqt = oneOf [ stringRep FromTop "TB"+ , stringRep FromLeft "LR"+ , stringRep FromBottom "BT"+ , stringRep FromRight "RL"+ ]++-- -----------------------------------------------------------------------------++-- | Geometries of shapes are affected by the attributes 'Regular',+-- 'Peripheries' and 'Orientation'.+data Shape+ = BoxShape -- ^ Has synonyms of /rect/ and /rectangle/.+ | Polygon -- ^ Also affected by 'Sides', 'Skew' and 'Distortion'.+ | Ellipse -- ^ Has synonym of /oval/.+ | Circle+ | PointShape -- ^ Only affected by 'Peripheries', 'Width' and+ -- 'Height'.+ | Egg+ | Triangle+ | PlainText -- ^ Has synonym of /none/. Recommended for+ -- 'HtmlLabel's.+ | DiamondShape+ | Trapezium+ | Parallelogram+ | House+ | Pentagon+ | Hexagon+ | Septagon+ | Octagon+ | DoubleCircle+ | DoubleOctagon+ | TripleOctagon+ | InvTriangle+ | InvTrapezium+ | InvHouse+ | MDiamond+ | MSquare+ | MCircle+ | Square+ | Star -- ^ Requires Graphviz >= 2.32.0.+ | Underline -- ^ Requires Graphviz >= 2.36.0.+ | Note+ | Tab+ | Folder+ | Box3D+ | Component+ | Promoter -- ^ Requires Graphviz >= 2.30.0.+ | CDS -- ^ Requires Graphviz >= 2.30.0.+ | Terminator -- ^ Requires Graphviz >= 2.30.0.+ | UTR -- ^ Requires Graphviz >= 2.30.0.+ | PrimerSite -- ^ Requires Graphviz >= 2.30.0.+ | RestrictionSite -- ^ Requires Graphviz >= 2.30.0.+ | FivePovOverhang -- ^ Requires Graphviz >= 2.30.0.+ | ThreePovOverhang -- ^ Requires Graphviz >= 2.30.0.+ | NoOverhang -- ^ Requires Graphviz >= 2.30.0.+ | Assembly -- ^ Requires Graphviz >= 2.30.0.+ | Signature -- ^ Requires Graphviz >= 2.30.0.+ | Insulator -- ^ Requires Graphviz >= 2.30.0.+ | Ribosite -- ^ Requires Graphviz >= 2.30.0.+ | RNAStab -- ^ Requires Graphviz >= 2.30.0.+ | ProteaseSite -- ^ Requires Graphviz >= 2.30.0.+ | ProteinStab -- ^ Requires Graphviz >= 2.30.0.+ | RPromoter -- ^ Requires Graphviz >= 2.30.0.+ | RArrow -- ^ Requires Graphviz >= 2.30.0.+ | LArrow -- ^ Requires Graphviz >= 2.30.0.+ | LPromoter -- ^ Requires Graphviz >= 2.30.0.+ | Record -- ^ Must specify the record shape with a 'Label'.+ | MRecord -- ^ Must specify the record shape with a 'Label'.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot Shape where+ unqtDot BoxShape = text "box"+ unqtDot Polygon = text "polygon"+ unqtDot Ellipse = text "ellipse"+ unqtDot Circle = text "circle"+ unqtDot PointShape = text "point"+ unqtDot Egg = text "egg"+ unqtDot Triangle = text "triangle"+ unqtDot PlainText = text "plaintext"+ unqtDot DiamondShape = text "diamond"+ unqtDot Trapezium = text "trapezium"+ unqtDot Parallelogram = text "parallelogram"+ unqtDot House = text "house"+ unqtDot Pentagon = text "pentagon"+ unqtDot Hexagon = text "hexagon"+ unqtDot Septagon = text "septagon"+ unqtDot Octagon = text "octagon"+ unqtDot DoubleCircle = text "doublecircle"+ unqtDot DoubleOctagon = text "doubleoctagon"+ unqtDot TripleOctagon = text "tripleoctagon"+ unqtDot InvTriangle = text "invtriangle"+ unqtDot InvTrapezium = text "invtrapezium"+ unqtDot InvHouse = text "invhouse"+ unqtDot MDiamond = text "Mdiamond"+ unqtDot MSquare = text "Msquare"+ unqtDot MCircle = text "Mcircle"+ unqtDot Square = text "square"+ unqtDot Star = text "star"+ unqtDot Underline = text "underline"+ unqtDot Note = text "note"+ unqtDot Tab = text "tab"+ unqtDot Folder = text "folder"+ unqtDot Box3D = text "box3d"+ unqtDot Component = text "component"+ unqtDot Promoter = text "promoter"+ unqtDot CDS = text "cds"+ unqtDot Terminator = text "terminator"+ unqtDot UTR = text "utr"+ unqtDot PrimerSite = text "primersite"+ unqtDot RestrictionSite = text "restrictionsite"+ unqtDot FivePovOverhang = text "fivepovoverhang"+ unqtDot ThreePovOverhang = text "threepovoverhang"+ unqtDot NoOverhang = text "nooverhang"+ unqtDot Assembly = text "assembly"+ unqtDot Signature = text "signature"+ unqtDot Insulator = text "insulator"+ unqtDot Ribosite = text "ribosite"+ unqtDot RNAStab = text "rnastab"+ unqtDot ProteaseSite = text "proteasesite"+ unqtDot ProteinStab = text "proteinstab"+ unqtDot RPromoter = text "rpromoter"+ unqtDot RArrow = text "rarrow"+ unqtDot LArrow = text "larrow"+ unqtDot LPromoter = text "lpromoter"+ unqtDot Record = text "record"+ unqtDot MRecord = text "Mrecord"++instance ParseDot Shape where+ parseUnqt = stringValue [ ("box3d", Box3D)+ , ("box", BoxShape)+ , ("rectangle", BoxShape)+ , ("rect", BoxShape)+ , ("polygon", Polygon)+ , ("ellipse", Ellipse)+ , ("oval", Ellipse)+ , ("circle", Circle)+ , ("point", PointShape)+ , ("egg", Egg)+ , ("triangle", Triangle)+ , ("plaintext", PlainText)+ , ("none", PlainText)+ , ("diamond", DiamondShape)+ , ("trapezium", Trapezium)+ , ("parallelogram", Parallelogram)+ , ("house", House)+ , ("pentagon", Pentagon)+ , ("hexagon", Hexagon)+ , ("septagon", Septagon)+ , ("octagon", Octagon)+ , ("doublecircle", DoubleCircle)+ , ("doubleoctagon", DoubleOctagon)+ , ("tripleoctagon", TripleOctagon)+ , ("invtriangle", InvTriangle)+ , ("invtrapezium", InvTrapezium)+ , ("invhouse", InvHouse)+ , ("Mdiamond", MDiamond)+ , ("Msquare", MSquare)+ , ("Mcircle", MCircle)+ , ("square", Square)+ , ("star", Star)+ , ("underline", Underline)+ , ("note", Note)+ , ("tab", Tab)+ , ("folder", Folder)+ , ("component", Component)+ , ("promoter", Promoter)+ , ("cds", CDS)+ , ("terminator", Terminator)+ , ("utr", UTR)+ , ("primersite", PrimerSite)+ , ("restrictionsite", RestrictionSite)+ , ("fivepovoverhang", FivePovOverhang)+ , ("threepovoverhang", ThreePovOverhang)+ , ("nooverhang", NoOverhang)+ , ("assembly", Assembly)+ , ("signature", Signature)+ , ("insulator", Insulator)+ , ("ribosite", Ribosite)+ , ("rnastab", RNAStab)+ , ("proteasesite", ProteaseSite)+ , ("proteinstab", ProteinStab)+ , ("rpromoter", RPromoter)+ , ("rarrow", RArrow)+ , ("larrow", LArrow)+ , ("lpromoter", LPromoter)+ , ("record", Record)+ , ("Mrecord", MRecord)+ ]++-- -----------------------------------------------------------------------------++data SmoothType = NoSmooth+ | AvgDist+ | GraphDist+ | PowerDist+ | RNG+ | Spring+ | TriangleSmooth+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot SmoothType where+ unqtDot NoSmooth = text "none"+ unqtDot AvgDist = text "avg_dist"+ unqtDot GraphDist = text "graph_dist"+ unqtDot PowerDist = text "power_dist"+ unqtDot RNG = text "rng"+ unqtDot Spring = text "spring"+ unqtDot TriangleSmooth = text "triangle"++instance ParseDot SmoothType where+ parseUnqt = oneOf [ stringRep NoSmooth "none"+ , stringRep AvgDist "avg_dist"+ , stringRep GraphDist "graph_dist"+ , stringRep PowerDist "power_dist"+ , stringRep RNG "rng"+ , stringRep Spring "spring"+ , stringRep TriangleSmooth "triangle"+ ]++-- -----------------------------------------------------------------------------++data StartType = StartStyle STStyle+ | StartSeed Int+ | StartStyleSeed STStyle Int+ deriving (Eq, Ord, Show, Read)++instance PrintDot StartType where+ unqtDot (StartStyle ss) = unqtDot ss+ unqtDot (StartSeed s) = unqtDot s+ unqtDot (StartStyleSeed ss s) = unqtDot ss <> unqtDot s++instance ParseDot StartType where+ parseUnqt = oneOf [ liftA2 StartStyleSeed parseUnqt parseUnqt+ , StartStyle <$> parseUnqt+ , StartSeed <$> parseUnqt+ ]++data STStyle = RegularStyle+ | SelfStyle+ | RandomStyle+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot STStyle where+ unqtDot RegularStyle = text "regular"+ unqtDot SelfStyle = text "self"+ unqtDot RandomStyle = text "random"++instance ParseDot STStyle where+ parseUnqt = oneOf [ stringRep RegularStyle "regular"+ , stringRep SelfStyle "self"+ , stringRep RandomStyle "random"+ ]++-- -----------------------------------------------------------------------------++-- | An individual style item. Except for 'DD', the @['String']@+-- should be empty.+data StyleItem = SItem StyleName [Text]+ deriving (Eq, Ord, Show, Read)++instance PrintDot StyleItem where+ unqtDot (SItem nm args)+ | null args = dnm+ | otherwise = dnm <> parens args'+ where+ dnm = unqtDot nm+ args' = hcat . punctuate comma $ mapM unqtDot args++ toDot si@(SItem nm args)+ | null args = toDot nm+ | otherwise = dquotes $ unqtDot si++ unqtListToDot = hcat . punctuate comma . mapM unqtDot++ listToDot [SItem nm []] = toDot nm+ listToDot sis = dquotes $ unqtListToDot sis++instance ParseDot StyleItem where+ parseUnqt = liftA2 SItem parseUnqt (tryParseList' parseArgs)++ parse = quotedParse (liftA2 SItem parseUnqt parseArgs)+ `onFail`+ fmap (`SItem` []) parse++ parseUnqtList = sepBy1 parseUnqt parseComma++ parseList = quotedParse parseUnqtList+ `onFail`+ -- Might not necessarily need to be quoted if a singleton...+ fmap return parse++parseArgs :: Parse [Text]+parseArgs = bracketSep (character '(')+ parseComma+ (character ')')+ parseStyleName++data StyleName = Dashed -- ^ Nodes and Edges+ | Dotted -- ^ Nodes and Edges+ | Solid -- ^ Nodes and Edges+ | Bold -- ^ Nodes and Edges+ | Invisible -- ^ Nodes and Edges+ | Filled -- ^ Nodes and Clusters+ | Striped -- ^ Rectangularly-shaped Nodes and+ -- Clusters; requires Graphviz >= 2.30.0+ | Wedged -- ^ Elliptically-shaped Nodes only;+ -- requires Graphviz >= 2.30.0+ | Diagonals -- ^ Nodes only+ | Rounded -- ^ Nodes and Clusters+ | Tapered -- ^ Edges only; requires Graphviz >=+ -- 2.29.0+ | Radial -- ^ Nodes, Clusters and Graphs, for use+ -- with 'GradientAngle'; requires+ -- Graphviz >= 2.29.0+ | DD Text -- ^ Device Dependent+ deriving (Eq, Ord, Show, Read)++instance PrintDot StyleName where+ unqtDot Dashed = text "dashed"+ unqtDot Dotted = text "dotted"+ unqtDot Solid = text "solid"+ unqtDot Bold = text "bold"+ unqtDot Invisible = text "invis"+ unqtDot Filled = text "filled"+ unqtDot Striped = text "striped"+ unqtDot Wedged = text "wedged"+ unqtDot Diagonals = text "diagonals"+ unqtDot Rounded = text "rounded"+ unqtDot Tapered = text "tapered"+ unqtDot Radial = text "radial"+ unqtDot (DD nm) = unqtDot nm++ toDot (DD nm) = toDot nm+ toDot sn = unqtDot sn++instance ParseDot StyleName where+ parseUnqt = checkDD <$> parseStyleName++ parse = quotedParse parseUnqt+ `onFail`+ fmap checkDD quotelessString++checkDD :: Text -> StyleName+checkDD str = case T.toLower str of+ "dashed" -> Dashed+ "dotted" -> Dotted+ "solid" -> Solid+ "bold" -> Bold+ "invis" -> Invisible+ "filled" -> Filled+ "striped" -> Striped+ "wedged" -> Wedged+ "diagonals" -> Diagonals+ "rounded" -> Rounded+ "tapered" -> Tapered+ "radial" -> Radial+ _ -> DD str++parseStyleName :: Parse Text+parseStyleName = liftA2 T.cons (orEscaped . noneOf $ ' ' : disallowedChars)+ (parseEscaped True [] disallowedChars)+ where+ disallowedChars = [quoteChar, '(', ')', ',']+ -- Used because the first character has slightly stricter requirements than the rest.+ orSlash p = stringRep '\\' "\\\\" `onFail` p+ orEscaped = orQuote . orSlash++-- -----------------------------------------------------------------------------++data ViewPort = VP { wVal :: Double+ , hVal :: Double+ , zVal :: Double+ , focus :: Maybe FocusType+ }+ deriving (Eq, Ord, Show, Read)++instance PrintDot ViewPort where+ unqtDot vp = maybe vs ((<>) (vs <> comma) . unqtDot)+ $ focus vp+ where+ vs = hcat . punctuate comma+ $ mapM (unqtDot . ($vp)) [wVal, hVal, zVal]++ toDot = dquotes . unqtDot++instance ParseDot ViewPort where+ parseUnqt = VP <$> parseUnqt+ <* parseComma+ <*> parseUnqt+ <* parseComma+ <*> parseUnqt+ <*> optional (parseComma *> parseUnqt)++ parse = quotedParse parseUnqt++-- | For use with 'ViewPort'.+data FocusType = XY Point+ | NodeFocus Text+ deriving (Eq, Ord, Show, Read)++instance PrintDot FocusType where+ unqtDot (XY p) = unqtDot p+ unqtDot (NodeFocus nm) = unqtDot nm++ toDot (XY p) = toDot p+ toDot (NodeFocus nm) = toDot nm++instance ParseDot FocusType where+ parseUnqt = fmap XY parseUnqt+ `onFail`+ fmap NodeFocus parseUnqt++ parse = fmap XY parse+ `onFail`+ fmap NodeFocus parse++-- -----------------------------------------------------------------------------++data VerticalPlacement = VTop+ | VCenter -- ^ Only valid for Nodes.+ | VBottom+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot VerticalPlacement where+ unqtDot VTop = char 't'+ unqtDot VCenter = char 'c'+ unqtDot VBottom = char 'b'++instance ParseDot VerticalPlacement where+ parseUnqt = oneOf [ stringRep VTop "t"+ , stringRep VCenter "c"+ , stringRep VBottom "b"+ ]++-- -----------------------------------------------------------------------------++-- | A list of search paths.+newtype Paths = Paths { paths :: [FilePath] }+ deriving (Eq, Ord, Show, Read)++instance PrintDot Paths where+ unqtDot = unqtDot . intercalate [searchPathSeparator] . paths++ toDot (Paths [p]) = toDot p+ toDot ps = dquotes $ unqtDot ps++instance ParseDot Paths where+ parseUnqt = Paths . splitSearchPath <$> parseUnqt++ parse = quotedParse parseUnqt+ `onFail`+ fmap (Paths . (:[]) . T.unpack) quotelessString++-- -----------------------------------------------------------------------------++data ScaleType = UniformScale+ | NoScale+ | FillWidth+ | FillHeight+ | FillBoth+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot ScaleType where+ unqtDot UniformScale = unqtDot True+ unqtDot NoScale = unqtDot False+ unqtDot FillWidth = text "width"+ unqtDot FillHeight = text "height"+ unqtDot FillBoth = text "both"++instance ParseDot ScaleType where+ parseUnqt = oneOf [ stringRep UniformScale "true"+ , stringRep NoScale "false"+ , stringRep FillWidth "width"+ , stringRep FillHeight "height"+ , stringRep FillBoth "both"+ ]++-- -----------------------------------------------------------------------------++data Justification = JLeft+ | JRight+ | JCenter+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot Justification where+ unqtDot JLeft = char 'l'+ unqtDot JRight = char 'r'+ unqtDot JCenter = char 'c'++instance ParseDot Justification where+ parseUnqt = oneOf [ stringRep JLeft "l"+ , stringRep JRight "r"+ , stringRep JCenter "c"+ ]++-- -----------------------------------------------------------------------------++data Ratios = AspectRatio Double+ | FillRatio+ | CompressRatio+ | ExpandRatio+ | AutoRatio+ deriving (Eq, Ord, Show, Read)++instance PrintDot Ratios where+ unqtDot (AspectRatio r) = unqtDot r+ unqtDot FillRatio = text "fill"+ unqtDot CompressRatio = text "compress"+ unqtDot ExpandRatio = text "expand"+ unqtDot AutoRatio = text "auto"++ toDot (AspectRatio r) = toDot r+ toDot r = unqtDot r++instance ParseDot Ratios where+ parseUnqt = parseRatio True++ parse = quotedParse parseUnqt <|> parseRatio False++parseRatio :: Bool -> Parse Ratios+parseRatio q = oneOf [ AspectRatio <$> parseSignedFloat q+ , stringRep FillRatio "fill"+ , stringRep CompressRatio "compress"+ , stringRep ExpandRatio "expand"+ , stringRep AutoRatio "auto"+ ]++-- -----------------------------------------------------------------------------++-- | A numeric type with an explicit separation between integers and+-- floating-point values.+data Number = Int Int+ | Dbl Double+ deriving (Eq, Ord, Show, Read)++instance PrintDot Number where+ unqtDot (Int i) = unqtDot i+ unqtDot (Dbl d) = unqtDot d++ toDot (Int i) = toDot i+ toDot (Dbl d) = toDot d++instance ParseDot Number where+ parseUnqt = parseNumber True++ parse = quotedParse parseUnqt+ <|>+ parseNumber False++parseNumber :: Bool -> Parse Number+parseNumber q = Dbl <$> parseStrictFloat q+ <|>+ Int <$> parseUnqt++-- -----------------------------------------------------------------------------++-- | If set, normalizes coordinates such that the first point is at+-- the origin and the first edge is at the angle if specified.+data Normalized = IsNormalized -- ^ Equivalent to @'NormalizedAngle' 0@.+ | NotNormalized+ | NormalizedAngle Double -- ^ Angle of first edge when+ -- normalized. Requires+ -- Graphviz >= 2.32.0.+ deriving (Eq, Ord, Show, Read)++instance PrintDot Normalized where+ unqtDot IsNormalized = unqtDot True+ unqtDot NotNormalized = unqtDot False+ unqtDot (NormalizedAngle a) = unqtDot a++ toDot (NormalizedAngle a) = toDot a+ toDot norm = unqtDot norm++instance ParseDot Normalized where+ parseUnqt = parseNormalized True++ parse = quotedParse parseUnqt <|> parseNormalized False++parseNormalized :: Bool -> Parse Normalized+parseNormalized q = NormalizedAngle <$> parseSignedFloat q+ <|>+ bool NotNormalized IsNormalized <$> onlyBool++-- -----------------------------------------------------------------------------++-- | Determine how the 'Width' and 'Height' attributes specify the+-- size of nodes.+data NodeSize = GrowAsNeeded+ -- ^ Nodes will be the smallest width and height+ -- needed to contain the label and any possible+ -- image. 'Width' and 'Height' are the minimum+ -- allowed sizes.+ | SetNodeSize+ -- ^ 'Width' and 'Height' dictate the size of the node+ -- with a warning if the label cannot fit in this.+ | SetShapeSize+ -- ^ 'Width' and 'Height' dictate the size of the+ -- shape only and the label can expand out of the+ -- shape (with a warning). Requires Graphviz >=+ -- 2.38.0.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot NodeSize where+ unqtDot GrowAsNeeded = unqtDot False+ unqtDot SetNodeSize = unqtDot True+ unqtDot SetShapeSize = text "shape"++instance ParseDot NodeSize where+ parseUnqt = bool GrowAsNeeded SetNodeSize <$> parseUnqt+ <|>+ stringRep SetShapeSize "shape"++-- -----------------------------------------------------------------------------++{-++As of Graphviz 2.36.0 this was commented out; as such it might come+back, so leave this here in case we need it again.++data AspectType = RatioOnly Double+ | RatioPassCount Double Int+ deriving (Eq, Ord, Show, Read)++instance PrintDot AspectType where+ unqtDot (RatioOnly r) = unqtDot r+ unqtDot (RatioPassCount r p) = commaDel r p++ toDot at@RatioOnly{} = unqtDot at+ toDot at@RatioPassCount{} = dquotes $ unqtDot at++instance ParseDot AspectType where+ parseUnqt = fmap (uncurry RatioPassCount) commaSepUnqt+ `onFail`+ fmap RatioOnly parseUnqt+++ parse = quotedParse (uncurry RatioPassCount <$> commaSepUnqt)+ `onFail`+ fmap RatioOnly parse++-}
Data/GraphViz/Commands.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses, OverloadedStrings #-} {- | Module : Data.GraphViz.Commands@@ -47,17 +47,18 @@ import Data.GraphViz.Types -- This is here just for Haddock linking purposes.-import Data.GraphViz.Attributes.Complete(GraphvizCommand(..))-import Data.GraphViz.Commands.IO(runCommand)+import Data.GraphViz.Commands.Available+import Data.GraphViz.Commands.IO (runCommand) import Data.GraphViz.Exception -import qualified Data.ByteString as SB-import Data.Maybe(isJust)-import System.IO(Handle, hSetBinaryMode, hPutStrLn, stderr)-import Control.Monad(liftM, unless)-import System.FilePath((<.>))-import System.Directory(findExecutable)-import System.Exit(ExitCode(..), exitWith)+import Control.Monad (liftM, unless)+import qualified Data.ByteString as SB+import Data.Maybe (isJust)+import Data.Version (Version (..), showVersion)+import System.Directory (findExecutable)+import System.Exit (ExitCode (..), exitWith)+import System.FilePath ((<.>))+import System.IO (Handle, hPutStrLn, hSetBinaryMode, stderr) -- ----------------------------------------------------------------------------- @@ -114,9 +115,11 @@ -- layout performed. | DotOutput -- ^ Reproduces the input along with -- layout information.- | XDot -- ^ As with 'DotOutput', but provides- -- even more information on how the- -- graph is drawn.+ | XDot (Maybe Version)+ -- ^ As with 'DotOutput', but provides even more+ -- information on how the graph is drawn. The+ -- optional 'Version' is the same as+ -- specifying the @XDotVersion@ attribute. | Eps -- ^ Encapsulated PostScript. | Fig -- ^ FIG graphics language. | Gd -- ^ Internal GD library format.@@ -157,13 +160,13 @@ -- for mobile computing devices. | WebP -- ^ Google's WebP format; requires -- Graphviz >= 2.29.0.- deriving (Eq, Ord, Bounded, Enum, Show, Read)+ deriving (Eq, Ord, Show, Read) instance GraphvizResult GraphvizOutput where outputCall Bmp = "bmp" outputCall Canon = "canon" outputCall DotOutput = "dot"- outputCall XDot = "xdot"+ outputCall (XDot mv) = "xdot" ++ maybe "" (showVersion . (\v -> v {versionTags = []})) mv outputCall Eps = "eps" outputCall Fig = "fig" outputCall Gd = "gd"@@ -193,9 +196,9 @@ -- | A default file extension for each 'GraphvizOutput'. defaultExtension :: GraphvizOutput -> String defaultExtension Bmp = "bmp"-defaultExtension Canon = "dot"-defaultExtension DotOutput = "dot"-defaultExtension XDot = "dot"+defaultExtension Canon = "gv"+defaultExtension DotOutput = "gv"+defaultExtension XDot{} = "gv" defaultExtension Eps = "eps" defaultExtension Fig = "fig" defaultExtension Gd = "gd"
+ Data/GraphViz/Commands/Available.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}+{- |+ Module : Data.GraphViz.Commands.Available+ Description : Available command-line programs+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ These are the known programs that read in Dot graphs.++ -}+module Data.GraphViz.Commands.Available where++import Data.GraphViz.Parsing+import Data.GraphViz.Printing++-- -----------------------------------------------------------------------------++-- | The available Graphviz commands. The following directions are+-- based upon those in the Graphviz man page (available online at+-- <http://graphviz.org/pdf/dot.1.pdf>, or if installed on your+-- system @man graphviz@). Note that any command can be used on+-- both directed and undirected graphs.+--+-- When used with the 'Layout' attribute, it overrides any actual+-- command called on the dot graph.+data GraphvizCommand = Dot -- ^ For hierachical graphs (ideal for+ -- directed graphs).+ | Neato -- ^ For symmetric layouts of graphs+ -- (ideal for undirected graphs).+ | TwoPi -- ^ For radial layout of graphs.+ | Circo -- ^ For circular layout of graphs.+ | Fdp -- ^ Spring-model approach for+ -- undirected graphs.+ | Sfdp -- ^ As with Fdp, but ideal for large+ -- graphs.+ | Osage -- ^ Filter for drawing clustered graphs,+ -- requires Graphviz >= 2.28.0.+ | Patchwork -- ^ Draw clustered graphs as treemaps,+ -- requires Graphviz >= 2.28.0.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot GraphvizCommand where+ unqtDot Dot = text "dot"+ unqtDot Neato = text "neato"+ unqtDot TwoPi = text "twopi"+ unqtDot Circo = text "circo"+ unqtDot Fdp = text "fdp"+ unqtDot Sfdp = text "sfdp"+ unqtDot Osage = text "osage"+ unqtDot Patchwork = text "patchwork"++instance ParseDot GraphvizCommand where+ parseUnqt = stringValue [ ("dot", Dot)+ , ("neato", Neato)+ , ("twopi", TwoPi)+ , ("circo", Circo)+ , ("fdp", Fdp)+ , ("sfdp", Sfdp)+ , ("osage", Osage)+ , ("patchwork", Patchwork)+ ]
Data/GraphViz/Commands/IO.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE MultiParamTypeClasses #-}+ {- | Module : Data.GraphViz.Commands.IO Description : IO-related functions for graphviz.@@ -26,29 +28,33 @@ , runCommand ) where -import Data.GraphViz.State(initialState)-import Data.GraphViz.Types(PrintDotRepr, ParseDotRepr, printDotGraph, parseDotGraph)-import Data.GraphViz.Printing(toDot) import Data.GraphViz.Exception-import Text.PrettyPrint.Leijen.Text(displayT, renderOneLine)+import Data.GraphViz.Internal.State (initialState)+import Data.GraphViz.Printing (toDot)+import Data.GraphViz.Types (ParseDotRepr, PrintDotRepr, parseDotGraph,+ printDotGraph)+import Text.PrettyPrint.Leijen.Text (displayT, renderOneLine) -import qualified Data.Text.Lazy.Encoding as T-import Data.Text.Encoding.Error(UnicodeException)-import Data.Text.Lazy(Text)-import qualified Data.ByteString as SB-import qualified Data.ByteString.Lazy as B-import Data.ByteString.Lazy(ByteString)-import Control.Monad(liftM)-import Control.Monad.Trans.State-import System.IO(Handle, IOMode(ReadMode,WriteMode)- , withFile, stdout, stdin, hPutChar- , hClose, hGetContents)-import System.IO.Temp(withSystemTempFile)-import System.Exit(ExitCode(ExitSuccess))-import System.Process(runInteractiveProcess, waitForProcess)-import System.FilePath((<.>))-import Control.Exception(IOException, evaluate, finally)-import Control.Concurrent(MVar, forkIO, newEmptyMVar, putMVar, takeMVar)+import Control.Concurrent (MVar, forkIO, newEmptyMVar, putMVar,+ takeMVar)+import Control.Exception (IOException, evaluate, finally)+import Control.Monad (liftM)+import Control.Monad.Trans.State+import qualified Data.ByteString as SB+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as B+import Data.Text.Encoding.Error (UnicodeException)+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy.Encoding as T+import System.Exit (ExitCode (ExitSuccess))+import System.FilePath ((<.>))+import System.IO (Handle,+ IOMode (ReadMode, WriteMode),+ hClose, hGetContents, hPutChar,+ stdin, stdout, withFile)+import System.IO.Temp (withSystemTempFile)+import System.Process (runInteractiveProcess,+ waitForProcess) -- -----------------------------------------------------------------------------
+ Data/GraphViz/Internal/State.hs view
@@ -0,0 +1,138 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}++{- |+ Module : Data.GraphViz.Internal.State+ Description : Printing and parsing state.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ When printing and parsing Dot code, some items depend on values+ that are set earlier.+-}+module Data.GraphViz.Internal.State+ ( GraphvizStateM(..)+ , GraphvizState(..)+ , AttributeType(..)+ , setAttributeType+ , getAttributeType+ , initialState+ , setDirectedness+ , getDirectedness+ , setLayerSep+ , getLayerSep+ , setLayerListSep+ , getLayerListSep+ , setColorScheme+ , getColorScheme+ ) where++import Data.GraphViz.Attributes.ColorScheme++import Control.Monad.Trans.State (State, gets, modify)+import Text.ParserCombinators.Poly.StateText (Parser, stQuery, stUpdate)++-- -----------------------------------------------------------------------------++class (Monad m) => GraphvizStateM m where+ modifyGS :: (GraphvizState -> GraphvizState) -> m ()++ getsGS :: (GraphvizState -> a) -> m a++instance GraphvizStateM (State GraphvizState) where+ modifyGS = modify++ getsGS = gets++instance GraphvizStateM (Parser GraphvizState) where+ modifyGS = stUpdate++ getsGS = stQuery++data AttributeType = GraphAttribute+ | SubGraphAttribute+ | ClusterAttribute+ | NodeAttribute+ | EdgeAttribute+ deriving (Eq, Ord, Show, Read)++-- | Several aspects of Dot code are either global or mutable state.+data GraphvizState = GS { parseStrictly :: !Bool+ -- ^ If 'False', allow fallbacks for+ -- attributes that don't match known+ -- specification when parsing.+ , directedEdges :: !Bool+ , layerSep :: [Char]+ , layerListSep :: [Char]+ , attributeType :: !AttributeType+ , graphColor :: !ColorScheme+ , clusterColor :: !ColorScheme+ , nodeColor :: !ColorScheme+ , edgeColor :: !ColorScheme+ }+ deriving (Eq, Ord, Show, Read)++initialState :: GraphvizState+initialState = GS { parseStrictly = True+ , directedEdges = True+ , layerSep = defLayerSep+ , layerListSep = defLayerListSep+ , attributeType = GraphAttribute+ , graphColor = X11+ , clusterColor = X11+ , nodeColor = X11+ , edgeColor = X11+ }++setDirectedness :: (GraphvizStateM m) => Bool -> m ()+setDirectedness d = modifyGS (\ gs -> gs { directedEdges = d } )++getDirectedness :: (GraphvizStateM m) => m Bool+getDirectedness = getsGS directedEdges++setAttributeType :: (GraphvizStateM m) => AttributeType -> m ()+setAttributeType tp = modifyGS $ \ gs -> gs { attributeType = tp }++getAttributeType :: (GraphvizStateM m) => m AttributeType+getAttributeType = getsGS attributeType++setLayerSep :: (GraphvizStateM m) => [Char] -> m ()+setLayerSep sep = modifyGS (\ gs -> gs { layerSep = sep } )++getLayerSep :: (GraphvizStateM m) => m [Char]+getLayerSep = getsGS layerSep++setLayerListSep :: (GraphvizStateM m) => [Char] -> m ()+setLayerListSep sep = modifyGS (\ gs -> gs { layerListSep = sep } )++getLayerListSep :: (GraphvizStateM m) => m [Char]+getLayerListSep = getsGS layerListSep++setColorScheme :: (GraphvizStateM m) => ColorScheme -> m ()+setColorScheme cs = do tp <- getsGS attributeType+ modifyGS $ \gs -> case tp of+ GraphAttribute -> gs { graphColor = cs }+ -- subgraphs don't have specified scheme+ SubGraphAttribute -> gs { graphColor = cs }+ ClusterAttribute -> gs { clusterColor = cs }+ NodeAttribute -> gs { nodeColor = cs }+ EdgeAttribute -> gs { edgeColor = cs }++getColorScheme :: (GraphvizStateM m) => m ColorScheme+getColorScheme = do tp <- getsGS attributeType+ getsGS $ case tp of+ GraphAttribute -> graphColor+ -- subgraphs don't have specified scheme+ SubGraphAttribute -> graphColor+ ClusterAttribute -> clusterColor+ NodeAttribute -> nodeColor+ EdgeAttribute -> edgeColor++-- | The default separators for 'LayerSep'.+defLayerSep :: [Char]+defLayerSep = [' ', ':', '\t']++-- | The default separators for 'LayerListSep'.+defLayerListSep :: [Char]+defLayerListSep = [',']
+ Data/GraphViz/Internal/Util.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE OverloadedStrings, PatternGuards #-}+{-# OPTIONS_HADDOCK hide #-}++{- |+ Module : Data.GraphViz.Internal.Util+ Description : Internal utility functions+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module defines internal utility functions.+-}+module Data.GraphViz.Internal.Util where++import Data.Char (isAsciiLower, isAsciiUpper, isDigit, ord)++import Control.Monad (liftM2)+import Data.Function (on)+import Data.List (groupBy, sortBy)+import Data.Maybe (isJust)+import Data.Set (Set)+import qualified Data.Set as Set+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.Read as T+import Data.Version (Version (..))++-- -----------------------------------------------------------------------------++isIDString :: Text -> Bool+isIDString = maybe False (\(f,os) -> frstIDString f && T.all restIDString os)+ . T.uncons++-- | First character of a non-quoted 'String' must match this.+frstIDString :: Char -> Bool+frstIDString c = any ($c) [ isAsciiUpper+ , isAsciiLower+ , (==) '_'+ , (\ x -> ord x >= 128)+ ]++-- | The rest of a non-quoted 'String' must match this.+restIDString :: Char -> Bool+restIDString c = frstIDString c || isDigit c++-- | Determine if this String represents a number.+isNumString :: Text -> Bool+isNumString "" = False+isNumString "-" = False+isNumString str = case T.uncons $ T.toLower str of+ Just ('-',str') -> go str'+ _ -> go str+ where+ -- Can't use Data.Text.Lazy.Read.double as it doesn't cover all+ -- possible cases+ go s = uncurry go' $ T.span isDigit s+ go' ds nds+ | T.null nds = True+ | T.null ds && nds == "." = False+ | T.null ds+ , Just ('.',nds') <- T.uncons nds+ , Just (d,nds'') <- T.uncons nds' = isDigit d && checkEs' nds''+ | Just ('.',nds') <- T.uncons nds = checkEs $ T.dropWhile isDigit nds'+ | T.null ds = False+ | otherwise = checkEs nds+ checkEs' s = case T.break ('e' ==) s of+ ("", _) -> False+ (ds,es) -> T.all isDigit ds && checkEs es+ checkEs str' = case T.uncons str' of+ Nothing -> True+ Just ('e',ds) -> isIntString ds+ _ -> False++{-+-- | This assumes that 'isNumString' is 'True'.+toDouble :: Text -> Double+toDouble str = case T.uncons $ T.toLower str of+ Just ('-', str') -> toD $ '-' `T.cons` adj str'+ _ -> toD $ adj str+ where+ adj s = T.cons '0'+ $ case T.span ('.' ==) s of+ (ds, ".") | not $ T.null ds -> s `T.snoc` '0'+ (ds, ds') | Just ('.',es) <- T.uncons ds'+ , Just ('e',es') <- T.uncons es+ -> ds `T.snoc` '.' `T.snoc` '0'+ `T.snoc` 'e' `T.snoc` '0' `T.append` es'+ _ -> s+ toD = either (const $ error "Not a Double") fst . T.signed T.double+-}+-- | This assumes that 'isNumString' is 'True'.+toDouble :: Text -> Double+toDouble str = case T.uncons $ T.toLower str of+ Just ('-', str') -> toD $ '-' `T.cons` adj str'+ _ -> toD $ adj str+ where+ adj s = T.cons '0'+ $ case T.span ('.' ==) s of+ (ds, ".") | not $ T.null ds -> s `T.snoc` '0'+ (ds, ds') | Just ('.',es) <- T.uncons ds'+ , Just ('e',_) <- T.uncons es+ -> ds `T.snoc` '.' `T.snoc` '0' `T.append` es+ _ -> s+ toD = read . T.unpack++isIntString :: Text -> Bool+isIntString = isJust . stringToInt++-- | Determine if this String represents an integer.+stringToInt :: Text -> Maybe Int+stringToInt str = case T.signed T.decimal str of+ Right (n, "") -> Just n+ _ -> Nothing++-- | Graphviz requires double quotes to be explicitly escaped.+escapeQuotes :: String -> String+escapeQuotes [] = []+escapeQuotes ('"':str) = '\\':'"': escapeQuotes str+escapeQuotes (c:str) = c : escapeQuotes str++-- | Remove explicit escaping of double quotes.+descapeQuotes :: String -> String+descapeQuotes [] = []+descapeQuotes ('\\':'"':str) = '"' : descapeQuotes str+descapeQuotes (c:str) = c : descapeQuotes str++isKeyword :: Text -> Bool+isKeyword = (`Set.member` keywords) . T.toLower++-- | The following are Dot keywords and are not valid as labels, etc. unquoted.+keywords :: Set Text+keywords = Set.fromList [ "node"+ , "edge"+ , "graph"+ , "digraph"+ , "subgraph"+ , "strict"+ ]++createVersion :: [Int] -> Version+createVersion bs = Version { versionBranch = bs, versionTags = []}++-- -----------------------------------------------------------------------------++uniq :: (Ord a) => [a] -> [a]+uniq = uniqBy id++uniqBy :: (Ord b) => (a -> b) -> [a] -> [a]+uniqBy f = map head . groupSortBy f++groupSortBy :: (Ord b) => (a -> b) -> [a] -> [[a]]+groupSortBy f = groupBy ((==) `on` f) . sortBy (compare `on` f)++groupSortCollectBy :: (Ord b) => (a -> b) -> (a -> c) -> [a] -> [(b,[c])]+groupSortCollectBy f g = map (liftM2 (,) (f . head) (map g)) . groupSortBy f++-- | Fold over 'Bool's; first param is for 'False', second for 'True'.+bool :: a -> a -> Bool -> a+bool f t b = if b+ then t+ else f++isSingle :: [a] -> Bool+isSingle [_] = True+isSingle _ = False
Data/GraphViz/Parsing.hs view
@@ -30,9 +30,10 @@ , parseIt' , runParser , runParser'+ , runParserWith+ , parseLiberally , checkValidParse -- * Convenience parsing combinators.- , bracket , ignoreSep , onlyBool , quotelessString@@ -47,6 +48,7 @@ , strings , character , parseStrictFloat+ , parseSignedFloat , noneOf , whitespace1 , whitespace@@ -75,31 +77,32 @@ , parseColorScheme ) where -import Data.GraphViz.Util-import Data.GraphViz.State+import Data.GraphViz.Exception (GraphvizException (NotDotCode), throw)+import Data.GraphViz.Internal.State+import Data.GraphViz.Internal.Util+ -- To avoid orphan instances and cyclic imports import Data.GraphViz.Attributes.ColorScheme-import Data.GraphViz.Exception(GraphvizException(NotDotCode), throw) -import Text.ParserCombinators.Poly.StateText hiding (bracket, empty, indent, runParser)+import Text.ParserCombinators.Poly.StateText hiding (empty, indent,+ runParser) import qualified Text.ParserCombinators.Poly.StateText as P-import Data.Char( isDigit- , isSpace- , isLower- , toLower- , toUpper- )-import Data.List(groupBy, sortBy)-import Data.Function(on)-import Data.Maybe(fromMaybe, isJust, isNothing, listToMaybe)-import Data.Ratio((%))-import qualified Data.Set as Set-import qualified Data.Text.Lazy as T++import Control.Arrow (first, second)+import Control.Monad (when)+import Data.Char (isDigit, isLower, isSpace, toLower,+ toUpper)+import Data.Function (on)+import Data.List (groupBy, sortBy)+import Data.Maybe (fromMaybe, isJust, isNothing, listToMaybe,+ maybeToList)+import Data.Ratio ((%))+import qualified Data.Set as Set+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.Read as T-import Data.Text.Lazy(Text)-import Data.Word(Word8, Word16)-import Control.Arrow(first, second)-import Control.Monad(when)+import Data.Version (Version (..))+import Data.Word (Word16, Word8) -- ----------------------------------------------------------------------------- -- Based off code from Text.Parse in the polyparse library@@ -107,10 +110,17 @@ -- | A @ReadS@-like type alias. type Parse a = Parser GraphvizState a -runParser :: Parse a -> Text -> (Either String a, Text)-runParser p t = let (r,_,t') = P.runParser p initialState t- in (r,t')+runParser :: Parse a -> Text -> (Either String a, Text)+runParser = runParserWith id +parseLiberally :: GraphvizState -> GraphvizState+parseLiberally gs = gs { parseStrictly = False }++runParserWith :: (GraphvizState -> GraphvizState) -> Parse a -> Text+ -> (Either String a, Text)+runParserWith f p t = let (r,_,t') = P.runParser p (f initialState) t+ in (r,t')+ -- | A variant of 'runParser' where it is assumed that the provided -- parsing function consumes all of the 'Text' input (with the -- exception of whitespace at the end).@@ -138,7 +148,7 @@ parseList = quotedParse parseUnqtList -- | Parse the required value, returning also the rest of the input--- 'String' that hasn't been parsed (for debugging purposes).+-- 'Text' that hasn't been parsed (for debugging purposes). parseIt :: (ParseDot a) => Text -> (a, Text) parseIt = first checkValidParse . runParser parse @@ -149,12 +159,12 @@ checkValidParse (Right a) = a -- | Parse the required value with the assumption that it will parse--- all of the input 'String'.+-- all of the input 'Text'. parseIt' :: (ParseDot a) => Text -> a parseIt' = runParser' parse instance ParseDot Int where- parseUnqt = parseInt'+ parseUnqt = parseSignedInt instance ParseDot Integer where parseUnqt = parseSigned parseInt@@ -166,8 +176,11 @@ parseUnqt = parseInt instance ParseDot Double where- parseUnqt = parseFloat'+ parseUnqt = parseSignedFloat True + parse = quotedParse parseUnqt+ <|> parseSignedFloat False+ parseUnqtList = sepBy1 parseUnqt (character ':') parseList = quotedParse parseUnqtList@@ -177,7 +190,7 @@ instance ParseDot Bool where parseUnqt = onlyBool `onFail`- fmap (zero /=) parseInt'+ fmap (zero /=) parseSignedInt where zero :: Int zero = 0@@ -200,6 +213,20 @@ parseList = T.unpack <$> parse +-- | Ignores 'versionTags' and assumes 'not . null . versionBranch'+-- (usually you want 'length . versionBranch == 2') and that all+-- such values are non-negative.+instance ParseDot Version where+ parseUnqt = createVersion <$> sepBy1 (parseIntCheck False) (character '.')++ parse = quotedParse parseUnqt+ <|>+ (createVersion .) . (. maybeToList) . (:)+ <$> (parseIntCheck False) <*> optional (character '.' *> parseInt)+ -- Leave the last one to check for possible decimals+ -- afterwards as there should be at most two version+ -- numbers here.+ instance ParseDot Text where -- Too many problems with using this within other parsers where -- using numString or stringBlock will cause a parse failure. As@@ -217,14 +244,14 @@ parse = parseList --- | Parse a 'String' that doesn't need to be quoted.+-- | Parse a 'Text' that doesn't need to be quoted. quotelessString :: Parse Text-quotelessString = numString `onFail` stringBlock+quotelessString = numString False `onFail` stringBlock -numString :: Parse Text-numString = fmap tShow parseStrictFloat- `onFail`- fmap tShow parseInt'+numString :: Bool -> Parse Text+numString q = fmap tShow (parseStrictFloat q)+ `onFail`+ fmap tShow parseSignedInt where tShow :: (Show a) => a -> Text tShow = T.pack . show@@ -242,68 +269,65 @@ p parseInt :: (Integral a) => Parse a-parseInt = do cs <- many1Satisfy isDigit- `adjustErr` ("Expected one or more digits\n\t"++)- case T.decimal cs of- Right (n,"") -> checkInt n- -- This case should never actually happen...- Right (_,txt) -> fail $ "Trailing digits not parsed as Integral: " ++ T.unpack txt- Left err -> fail $ "Could not read Integral: " ++ err+parseInt = parseIntCheck True++-- | Flag indicates whether to check whether the number is actually a+-- floating-point value.+parseIntCheck :: (Integral a) => Bool -> Parse a+parseIntCheck ch = do cs <- many1Satisfy isDigit+ `adjustErr` ("Expected one or more digits\n\t"++)+ case T.decimal cs of+ Right (n,"") -> bool return checkInt ch n+ -- This case should never actually happen...+ Right (_,txt) -> fail $ "Trailing digits not parsed as Integral: " ++ T.unpack txt+ Left err -> fail $ "Could not read Integral: " ++ err where checkInt n = do c <- optional $ oneOf [ character '.', character 'e' ] if isJust c then fail "This number is actually Floating, not Integral!" else return n -parseInt' :: Parse Int-parseInt' = parseSigned parseInt+parseSignedInt :: Parse Int+parseSignedInt = parseSigned parseInt -- | Parse a floating point number that actually contains decimals.-parseStrictFloat :: Parse Double-parseStrictFloat = parseSigned parseFloat+-- Bool flag indicates whether values that need to be quoted are+-- parsed.+parseStrictFloat :: Bool -> Parse Double+parseStrictFloat = parseSigned . parseFloat -parseFloat :: (RealFrac a) => Parse a-parseFloat = do ds <- manySatisfy isDigit- frac <- optional $ character '.' *> manySatisfy isDigit- when (T.null ds && noDec frac)- (fail "No actual digits in floating point number!")- expn <- optional parseExp- when (isNothing frac && isNothing expn)- (fail "This is an integer, not a floating point number!")- let frac' = fromMaybe "" frac- expn' = fromMaybe 0 expn- ( return . fromRational . (* (10^^(expn' - fromIntegral (T.length frac'))))- . (%1) . runParser' parseInt) (ds `T.append` frac')- `onFail`- fail "Expected a floating point number"+-- | Bool flag indicates whether to allow parsing exponentiated term,+-- as this is only allowed when quoted.+parseFloat :: (RealFrac a) => Bool -> Parse a+parseFloat q = do ds <- manySatisfy isDigit+ frac <- optional $ character '.' *> manySatisfy isDigit+ when (T.null ds && noDec frac)+ (fail "No actual digits in floating point number!")+ expn <- bool (pure Nothing) (optional parseExp) q+ when (isNothing frac && isNothing expn)+ (fail "This is an integer, not a floating point number!")+ let frac' = fromMaybe "" frac+ expn' = fromMaybe 0 expn+ ( return . fromRational . (* (10^^(expn' - fromIntegral (T.length frac'))))+ . (%1) . runParser' parseInt) (ds `T.append` frac')+ `onFail`+ fail "Expected a floating point number" where parseExp = character 'e' *> ((character '+' *> parseInt) `onFail`- parseInt')+ parseSignedInt) noDec = maybe True T.null -parseFloat' :: Parse Double-parseFloat' = parseSigned ( parseFloat- `onFail`- fmap fI parseInt- )+-- Bool indicates whether we can parse values that need quotes.+parseSignedFloat :: Bool -> Parse Double+parseSignedFloat q = parseSigned ( parseFloat q <|> fmap fI parseInt ) where fI :: Integer -> Double fI = fromIntegral -- ----------------------------------------------------------------------------- --- | Parse a bracketed item, discarding the brackets.------ The definition of @bracket@ defined in Polyparse uses--- 'adjustErrBad' and thus doesn't allow backtracking and trying the--- next possible parser. This is a version of @bracket@ that does.-bracket :: Parse bra -> Parse ket -> Parse a -> Parse a-bracket open close pa = (open `adjustErr` ("Missing opening bracket:\n\t"++))- *> pa- <* (close `adjustErr` ("Was expecting closing bracket:\n\t"++))- parseAndSpace :: Parse a -> Parse a parseAndSpace p = p `discard` whitespace @@ -331,6 +355,8 @@ strings :: [String] -> Parse () strings = oneOf . map string +-- | Assumes that any letter is ASCII for case-insensitive+-- comparisons. character :: Char -> Parse Char character c = satisfy parseC `adjustErr`@@ -378,11 +404,10 @@ quoteChar :: Char quoteChar = '"' --- | Parse a 'String' where the provided 'Char's (as well as @\"@ and+-- | Parse a 'Text' where the provided 'Char's (as well as @\"@ and -- @\\@) are escaped and the second list of 'Char's are those that -- are not permitted. Note: does not parse surrounding quotes. The--- 'Bool' value indicates whether empty 'String's are allowed or--- not.+-- 'Bool' value indicates whether empty 'Text's are allowed or not. parseEscaped :: Bool -> [Char] -> [Char] -> Parse Text parseEscaped empt cs bnd = fmap T.pack . lots $ qPrs `onFail` oth where
Data/GraphViz/Printing.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances, OverloadedStrings, TypeSynonymInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} {- | Module : Data.GraphViz.Printing@@ -47,7 +48,7 @@ module Data.GraphViz.Printing ( module Text.PrettyPrint.Leijen.Text.Monadic , DotCode- , renderDot -- Exported for Data.GraphViz.Types.printSGID+ , renderDot -- Exported for Data.GraphViz.Types.Internal.Common.printSGID , PrintDot(..) , unqtText , dotText@@ -63,33 +64,29 @@ , printColorScheme ) where -import Data.GraphViz.Util-import Data.GraphViz.State+import Data.GraphViz.Internal.State+import Data.GraphViz.Internal.Util -- To avoid orphan instances and cyclic imports import Data.GraphViz.Attributes.ColorScheme -- Only implicitly import and re-export combinators.-import Text.PrettyPrint.Leijen.Text.Monadic hiding ( SimpleDoc(..)- , renderPretty- , renderCompact- , displayT- , displayIO- , putDoc- , hPutDoc- , Pretty(..)- , bool- , string- , width- , (<$>))+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Text.PrettyPrint.Leijen.Text.Monadic hiding (Pretty (..),+ SimpleDoc (..), bool,+ displayIO, displayT,+ hPutDoc, putDoc,+ renderCompact,+ renderPretty, string,+ width, (<$>)) import qualified Text.PrettyPrint.Leijen.Text.Monadic as PP-import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text) -import Data.Char(toLower)-import qualified Data.Set as Set-import Data.Word(Word8, Word16)-import Control.Monad(ap, when)-import Control.Monad.Trans.State+import Control.Monad (ap, when)+import Control.Monad.Trans.State+import Data.Char (toLower)+import qualified Data.Set as Set+import Data.Version (Version (..))+import Data.Word (Word16, Word8) -- ----------------------------------------------------------------------------- @@ -178,6 +175,14 @@ unqtListToDot = unqtDot . T.pack listToDot = toDot . T.pack++-- | Ignores 'versionTags' and assumes 'not . null . versionBranch'+-- (usually you want 'length . versionBranch == 2').+instance PrintDot Version where+ unqtDot = hcat . punctuate dot . mapM int . versionBranch++ toDot v = bool id dquotes (not . null . drop 2 . versionBranch $ v)+ $ unqtDot v instance PrintDot Text where unqtDot = unqtString
− Data/GraphViz/State.hs
@@ -1,132 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}--{- |- Module : Data.GraphViz.State- Description : Printing and parsing state.- Copyright : (c) Ivan Lazar Miljenovic- License : 3-Clause BSD-style- Maintainer : Ivan.Miljenovic@gmail.com-- When printing and parsing Dot code, some items depend on values- that are set earlier.--}-module Data.GraphViz.State- ( GraphvizStateM(..)- , GraphvizState(..)- , AttributeType(..)- , setAttributeType- , getAttributeType- , initialState- , setDirectedness- , getDirectedness- , setLayerSep- , getLayerSep- , setLayerListSep- , getLayerListSep- , setColorScheme- , getColorScheme- ) where--import Data.GraphViz.Attributes.ColorScheme--import Control.Monad.Trans.State(State, modify, gets)-import Text.ParserCombinators.Poly.StateText(Parser, stUpdate, stQuery)---- -------------------------------------------------------------------------------class (Monad m) => GraphvizStateM m where- modifyGS :: (GraphvizState -> GraphvizState) -> m ()-- getsGS :: (GraphvizState -> a) -> m a--instance GraphvizStateM (State GraphvizState) where- modifyGS = modify-- getsGS = gets--instance GraphvizStateM (Parser GraphvizState) where- modifyGS = stUpdate-- getsGS = stQuery--data AttributeType = GraphAttribute- | SubGraphAttribute- | ClusterAttribute- | NodeAttribute- | EdgeAttribute- deriving (Eq, Ord, Show, Read)---- | Several aspects of Dot code are either global or mutable state.-data GraphvizState = GS { directedEdges :: !Bool- , layerSep :: [Char]- , layerListSep :: [Char]- , attributeType :: !AttributeType- , graphColor :: !ColorScheme- , clusterColor :: !ColorScheme- , nodeColor :: !ColorScheme- , edgeColor :: !ColorScheme- }- deriving (Eq, Ord, Show, Read)--initialState :: GraphvizState-initialState = GS { directedEdges = True- , layerSep = defLayerSep- , layerListSep = defLayerListSep- , attributeType = GraphAttribute- , graphColor = X11- , clusterColor = X11- , nodeColor = X11- , edgeColor = X11- }--setDirectedness :: (GraphvizStateM m) => Bool -> m ()-setDirectedness d = modifyGS (\ gs -> gs { directedEdges = d } )--getDirectedness :: (GraphvizStateM m) => m Bool-getDirectedness = getsGS directedEdges--setAttributeType :: (GraphvizStateM m) => AttributeType -> m ()-setAttributeType tp = modifyGS $ \ gs -> gs { attributeType = tp }--getAttributeType :: (GraphvizStateM m) => m AttributeType-getAttributeType = getsGS attributeType--setLayerSep :: (GraphvizStateM m) => [Char] -> m ()-setLayerSep sep = modifyGS (\ gs -> gs { layerSep = sep } )--getLayerSep :: (GraphvizStateM m) => m [Char]-getLayerSep = getsGS layerSep--setLayerListSep :: (GraphvizStateM m) => [Char] -> m ()-setLayerListSep sep = modifyGS (\ gs -> gs { layerListSep = sep } )--getLayerListSep :: (GraphvizStateM m) => m [Char]-getLayerListSep = getsGS layerListSep--setColorScheme :: (GraphvizStateM m) => ColorScheme -> m ()-setColorScheme cs = do tp <- getsGS attributeType- modifyGS $ \gs -> case tp of- GraphAttribute -> gs { graphColor = cs }- -- subgraphs don't have specified scheme- SubGraphAttribute -> gs { graphColor = cs }- ClusterAttribute -> gs { clusterColor = cs }- NodeAttribute -> gs { nodeColor = cs }- EdgeAttribute -> gs { edgeColor = cs }--getColorScheme :: (GraphvizStateM m) => m ColorScheme-getColorScheme = do tp <- getsGS attributeType- getsGS $ case tp of- GraphAttribute -> graphColor- -- subgraphs don't have specified scheme- SubGraphAttribute -> graphColor- ClusterAttribute -> clusterColor- NodeAttribute -> nodeColor- EdgeAttribute -> edgeColor---- | The default separators for 'LayerSep'.-defLayerSep :: [Char]-defLayerSep = [' ', ':', '\t']---- | The default separators for 'LayerListSep'.-defLayerListSep :: [Char]-defLayerListSep = [',']
Data/GraphViz/Types.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses,+ TypeSynonymInstances #-} {- | Module : Data.GraphViz.Types@@ -35,30 +36,30 @@ > digraph G { >- > subgraph cluster_0 {- > style=filled;- > color=lightgrey;- > node [style=filled,color=white];- > a0 -> a1 -> a2 -> a3;- > label = "process #1";- > }+ > subgraph cluster_0 {+ > style=filled;+ > color=lightgrey;+ > node [style=filled,color=white];+ > a0 -> a1 -> a2 -> a3;+ > label = "process #1";+ > } >- > subgraph cluster_1 {- > node [style=filled];- > b0 -> b1 -> b2 -> b3;- > label = "process #2";- > color=blue- > }- > start -> a0;- > start -> b0;- > a1 -> b3;- > b2 -> a3;- > a3 -> a0;- > a3 -> end;- > b3 -> end;+ > subgraph cluster_1 {+ > node [style=filled];+ > b0 -> b1 -> b2 -> b3;+ > label = "process #2";+ > color=blue+ > }+ > start -> a0;+ > start -> b0;+ > a1 -> b3;+ > b2 -> a3;+ > a3 -> a0;+ > a3 -> end;+ > b3 -> end; >- > start [shape=Mdiamond];- > end [shape=Msquare];+ > start [shape=Mdiamond];+ > end [shape=Msquare]; > } Each representation is suited for different things:@@ -94,6 +95,7 @@ , PPDotRepr -- * Common sub-types , GraphID(..)+ , Number (..) , ToGraphID(..) , textGraphID , GlobalAttributes(..)@@ -112,26 +114,33 @@ -- * Printing and parsing a @DotRepr@. , printDotGraph , parseDotGraph+ , parseDotGraphLiberally -- * Limitations and documentation -- $limitations ) where -import Data.GraphViz.Types.Canonical( DotGraph(..), DotStatements(..)- , DotSubGraph(..))-import Data.GraphViz.Types.Common( GraphID(..), GlobalAttributes(..), withGlob- , DotNode(..), DotEdge(..), numericValue)+import Data.GraphViz.Attributes.Complete (rmUnwantedAttributes,+ usedByClusters, usedByEdges,+ usedByGraphs, usedByNodes)+import Data.GraphViz.Internal.State (GraphvizState)+import Data.GraphViz.Internal.Util (bool)+import Data.GraphViz.Parsing (ParseDot (..), adjustErr,+ checkValidParse, parse,+ parseLiberally, runParserWith)+import Data.GraphViz.PreProcessing (preProcess)+import Data.GraphViz.Printing (PrintDot (..), printIt)+import Data.GraphViz.Types.Canonical (DotGraph (..), DotStatements (..),+ DotSubGraph (..))+import Data.GraphViz.Types.Internal.Common (DotEdge (..), DotNode (..),+ GlobalAttributes (..), GraphID (..),+ Number (..), numericValue, withGlob) import Data.GraphViz.Types.State-import Data.GraphViz.Attributes.Complete( rmUnwantedAttributes, usedByGraphs- , usedByClusters, usedByNodes, usedByEdges)-import Data.GraphViz.Util(bool)-import Data.GraphViz.Parsing(ParseDot(..), runParser, checkValidParse, parse, adjustErr)-import Data.GraphViz.PreProcessing(preProcess)-import Data.GraphViz.Printing(PrintDot(..), printIt) -import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)-import Control.Arrow(first, second, (***))-import Control.Monad.Trans.State(get, put, modify, execState, evalState)+import Control.Arrow (first, second, (***))+import Control.Monad.Trans.State (evalState, execState, get, modify,+ put)+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T -- ----------------------------------------------------------------------------- @@ -147,6 +156,9 @@ class (Ord n) => DotRepr dg n where -- | Convert from a graph in canonical form. This is especially -- useful when using the functions from "Data.GraphViz.Algorithms".+ --+ -- See @FromGeneralisedDot@ in "Data.GraphViz.Types.Generalised"+ -- for a semi-inverse of this function. fromCanonical :: DotGraph n -> dg n -- | Return the ID of the graph.@@ -260,9 +272,23 @@ -- -- Also removes any comments, etc. before parsing. parseDotGraph :: (ParseDotRepr dg n) => Text -> dg n-parseDotGraph = fst . prs . preProcess+parseDotGraph = parseDotGraphWith id++-- | As with 'parseDotGraph', but if an 'Attribute' cannot be parsed+-- strictly according to the known rules, let it fall back to being+-- parsed as an 'UnknownAttribute'. This is especially useful for+-- when using a version of Graphviz that is either newer (especially+-- for the XDot attributes) or older (when some attributes have+-- changed) but you'd still prefer it to parse rather than throwing+-- an error.+parseDotGraphLiberally :: (ParseDotRepr dg n) => Text -> dg n+parseDotGraphLiberally = parseDotGraphWith parseLiberally++parseDotGraphWith :: (ParseDotRepr dg n) => (GraphvizState -> GraphvizState)+ -> Text -> dg n+parseDotGraphWith f = fst . prs . preProcess where- prs = first checkValidParse . runParser parse'+ prs = first checkValidParse . runParserWith f parse' parse' = parse `adjustErr` ("Unable to parse the Dot graph; usually this is because of either:\n\@@ -342,7 +368,7 @@ sgRe sg = do sgid' <- case subGraphID sg of Nothing -> do n <- get put $ succ n- return . Just $ Int n+ return . Just . Num $ Int n sgid -> return sgid stmts' <- stRe $ subGraphStmts sg return $ sg { subGraphID = sgid'@@ -385,14 +411,14 @@ toGraphID = toGraphID . T.singleton instance ToGraphID Int where- toGraphID = Int+ toGraphID = Num . Int -- | This instance loses precision by going via 'Int'. instance ToGraphID Integer where- toGraphID = Int . fromInteger+ toGraphID = Num . Int . fromInteger instance ToGraphID Double where- toGraphID = Dbl+ toGraphID = Num . Dbl -- -----------------------------------------------------------------------------
Data/GraphViz/Types/Canonical.hs view
@@ -84,13 +84,13 @@ , DotEdge(..) ) where -import Data.GraphViz.Types.Common+import Data.GraphViz.Internal.State (AttributeType (..))+import Data.GraphViz.Internal.Util (bool) import Data.GraphViz.Parsing import Data.GraphViz.Printing-import Data.GraphViz.State(AttributeType(..))-import Data.GraphViz.Util(bool)+import Data.GraphViz.Types.Internal.Common -import Control.Arrow((&&&))+import Control.Arrow ((&&&)) -- -----------------------------------------------------------------------------
− Data/GraphViz/Types/Common.hs
@@ -1,528 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_HADDOCK hide #-}--{- |- Module : Data.GraphViz.Types.Common- Description : Common internal functions for dealing with overall types.- Copyright : (c) Ivan Lazar Miljenovic- License : 3-Clause BSD-style- Maintainer : Ivan.Miljenovic@gmail.com-- This module provides common functions used by both- "Data.GraphViz.Types" as well as "Data.GraphViz.Types.Generalised".--}-module Data.GraphViz.Types.Common where--import Data.GraphViz.Parsing-import Data.GraphViz.Printing-import Data.GraphViz.State-import Data.GraphViz.Util-import Data.GraphViz.Attributes.Complete( Attributes, Attribute(HeadPort, TailPort)- , usedByGraphs, usedByClusters- , usedByNodes)-import Data.GraphViz.Attributes.Internal(PortPos, parseEdgeBasedPP)--import Data.Maybe(isJust)-import qualified Data.Text.Lazy as T-import qualified Data.Text.Lazy.Read as T-import Data.Text.Lazy(Text)-import Control.Monad(when, unless)---- -------------------------------------------------------------------------------- This is re-exported by Data.GraphViz.Types---- | A polymorphic type that covers all possible ID values allowed by--- Dot syntax. Note that whilst the 'ParseDot' and 'PrintDot'--- instances for 'String' will properly take care of the special--- cases for numbers, they are treated differently here.-data GraphID = Str Text- | Int Int- | Dbl Double- deriving (Eq, Ord, Show, Read)--instance PrintDot GraphID where- unqtDot (Str str) = unqtDot str- unqtDot (Int i) = unqtDot i- unqtDot (Dbl d) = unqtDot d-- toDot (Str str) = toDot str- toDot gID = unqtDot gID--instance ParseDot GraphID where- parseUnqt = stringNum <$> parseUnqt-- parse = stringNum <$> parse- `adjustErr`- ("Not a valid GraphID\n\t"++)--stringNum :: Text -> GraphID-stringNum str = maybe checkDbl Int $ stringToInt str- where- checkDbl = if isNumString str- then Dbl $ toDouble str- else Str str--numericValue :: GraphID -> Maybe Int-numericValue (Str str) = either (const Nothing) (Just . round . fst)- $ T.signed T.double str-numericValue (Int n) = Just n-numericValue (Dbl x) = Just $ round x---- --------------------------------------------------------------------------------- Re-exported by Data.GraphViz.Types.*---- | Represents a list of top-level list of 'Attribute's for the--- entire graph/sub-graph. Note that 'GraphAttrs' also applies to--- 'DotSubGraph's.------ Note that Dot allows a single 'Attribute' to be listed on a line;--- if this is the case then when parsing, the type of 'Attribute' it--- is determined and that type of 'GlobalAttribute' is created.-data GlobalAttributes = GraphAttrs { attrs :: Attributes }- | NodeAttrs { attrs :: Attributes }- | EdgeAttrs { attrs :: Attributes }- deriving (Eq, Ord, Show, Read)--instance PrintDot GlobalAttributes where- unqtDot = printAttrBased True printGlobAttrType globAttrType attrs-- unqtListToDot = printAttrBasedList True printGlobAttrType globAttrType attrs-- listToDot = unqtListToDot---- GraphAttrs, NodeAttrs and EdgeAttrs respectively-partitionGlobal :: [GlobalAttributes] -> (Attributes, Attributes, Attributes)-partitionGlobal = foldr select ([], [], [])- where- select globA ~(gs,ns,es) = case globA of- GraphAttrs as -> (as ++ gs, ns, es)- NodeAttrs as -> (gs, as ++ ns, es)- EdgeAttrs as -> (gs, ns, as ++ es)--unPartitionGlobal :: (Attributes, Attributes, Attributes) -> [GlobalAttributes]-unPartitionGlobal (gas,nas,eas) = [ GraphAttrs gas- , NodeAttrs nas- , EdgeAttrs eas- ]--printGlobAttrType :: GlobalAttributes -> DotCode-printGlobAttrType GraphAttrs{} = text "graph"-printGlobAttrType NodeAttrs{} = text "node"-printGlobAttrType EdgeAttrs{} = text "edge"--instance ParseDot GlobalAttributes where- -- Not using parseAttrBased here because we want to force usage of- -- Attributes.- parseUnqt = do gat <- parseGlobAttrType-- -- Determine if we need to set the attribute type.- let mtp = globAttrType $ gat [] -- Only need the constructor- oldTp <- getAttributeType- maybe (return ()) setAttributeType mtp-- as <- whitespace *> parse-- -- Safe to set back even if not changed.- setAttributeType oldTp- return $ gat as- `onFail`- fmap determineType parse-- parse = parseUnqt -- Don't want the option of quoting- `adjustErr`- ("Not a valid listing of global attributes\n\t"++)-- -- Have to do this manually because of the special case- parseUnqtList = parseStatements parseUnqt-- parseList = parseUnqtList---- Cheat: rather than determine whether it's a graph, cluster or--- sub-graph just don't set it.-globAttrType :: GlobalAttributes -> Maybe AttributeType-globAttrType NodeAttrs{} = Just NodeAttribute-globAttrType EdgeAttrs{} = Just EdgeAttribute-globAttrType _ = Nothing--parseGlobAttrType :: Parse (Attributes -> GlobalAttributes)-parseGlobAttrType = oneOf [ stringRep GraphAttrs "graph"- , stringRep NodeAttrs "node"- , stringRep EdgeAttrs "edge"- ]--determineType :: Attribute -> GlobalAttributes-determineType attr- | usedByGraphs attr = GraphAttrs attr'- | usedByClusters attr = GraphAttrs attr' -- Also covers SubGraph case- | usedByNodes attr = NodeAttrs attr'- | otherwise = EdgeAttrs attr' -- Must be for edges.- where- attr' = [attr]--withGlob :: (Attributes -> Attributes) -> GlobalAttributes -> GlobalAttributes-withGlob f (GraphAttrs as) = GraphAttrs $ f as-withGlob f (NodeAttrs as) = NodeAttrs $ f as-withGlob f (EdgeAttrs as) = EdgeAttrs $ f as---- --------------------------------------------------------------------------------- | A node in 'DotGraph'.-data DotNode n = DotNode { nodeID :: n- , nodeAttributes :: Attributes- }- deriving (Eq, Ord, Show, Read)--instance (PrintDot n) => PrintDot (DotNode n) where- unqtDot = printAttrBased False printNodeID- (const $ Just NodeAttribute) nodeAttributes-- unqtListToDot = printAttrBasedList False printNodeID- (const $ Just NodeAttribute) nodeAttributes-- listToDot = unqtListToDot--printNodeID :: (PrintDot n) => DotNode n -> DotCode-printNodeID = toDot . nodeID--instance (ParseDot n) => ParseDot (DotNode n) where- parseUnqt = parseAttrBased NodeAttribute False parseNodeID-- parse = parseUnqt -- Don't want the option of quoting-- parseUnqtList = parseAttrBasedList NodeAttribute False parseNodeID-- parseList = parseUnqtList--parseNodeID :: (ParseDot n) => Parse (Attributes -> DotNode n)-parseNodeID = DotNode <$> parseAndCheck- where- parseAndCheck = do n <- parse- me <- optional parseUnwanted- maybe (return n) (const notANode) me- notANode = fail "This appears to be an edge, not a node"- parseUnwanted = oneOf [ parseEdgeType *> return ()- , character ':' *> return () -- PortPos value- ]--instance Functor DotNode where- fmap f n = n { nodeID = f $ nodeID n }---- --------------------------------------------------------------------------------- This is re-exported in Data.GraphViz.Types; defined here so that--- Generalised can access and use parseEdgeLine (needed for "a -> b ->--- c"-style edge statements).---- | An edge in 'DotGraph'.-data DotEdge n = DotEdge { fromNode :: n- , toNode :: n- , edgeAttributes :: Attributes- }- deriving (Eq, Ord, Show, Read)--instance (PrintDot n) => PrintDot (DotEdge n) where- unqtDot = printAttrBased False printEdgeID- (const $ Just EdgeAttribute) edgeAttributes-- unqtListToDot = printAttrBasedList False printEdgeID- (const $ Just EdgeAttribute) edgeAttributes-- listToDot = unqtListToDot--printEdgeID :: (PrintDot n) => DotEdge n -> DotCode-printEdgeID e = do isDir <- getDirectedness- toDot (fromNode e)- <+> bool undirEdge' dirEdge' isDir- <+> toDot (toNode e)---instance (ParseDot n) => ParseDot (DotEdge n) where- parseUnqt = parseAttrBased EdgeAttribute False parseEdgeID-- parse = parseUnqt -- Don't want the option of quoting-- -- Have to take into account edges of the type "n1 -> n2 -> n3", etc.- parseUnqtList = concat <$> parseStatements parseEdgeLine-- parseList = parseUnqtList--parseEdgeID :: (ParseDot n) => Parse (Attributes -> DotEdge n)-parseEdgeID = ignoreSep mkEdge parseEdgeNode parseEdgeType parseEdgeNode- `adjustErr`- ("Parsed beginning of DotEdge but could not parse Attributes:\n\t"++)- -- Parse both edge types just to be more liberal--type EdgeNode n = (n, Maybe PortPos)---- | Takes into account edge statements containing something like--- @a -> \{b c\}@.-parseEdgeNodes :: (ParseDot n) => Parse [EdgeNode n]-parseEdgeNodes = parseBraced ( wrapWhitespace- -- Should really use sepBy1, but this will do.- $ parseStatements parseEdgeNode- )- `onFail`- fmap (:[]) parseEdgeNode--parseEdgeNode :: (ParseDot n) => Parse (EdgeNode n)-parseEdgeNode = liftA2 (,) parse- (optional $ character ':' *> parseEdgeBasedPP)--mkEdge :: EdgeNode n -> EdgeNode n -> Attributes -> DotEdge n-mkEdge (eFrom, mFP) (eTo, mTP) = DotEdge eFrom eTo- . addPortPos TailPort mFP- . addPortPos HeadPort mTP--mkEdges :: [EdgeNode n] -> [EdgeNode n]- -> Attributes -> [DotEdge n]-mkEdges fs ts as = liftA2 (\f t -> mkEdge f t as) fs ts--addPortPos :: (PortPos -> Attribute) -> Maybe PortPos- -> Attributes -> Attributes-addPortPos c = maybe id ((:) . c)--parseEdgeType :: Parse Bool-parseEdgeType = wrapWhitespace $ stringRep True dirEdge- `onFail`- stringRep False undirEdge--parseEdgeLine :: (ParseDot n) => Parse [DotEdge n]-parseEdgeLine = do n1 <- parseEdgeNodes- ens <- many1 $ parseEdgeType *> parseEdgeNodes- let ens' = n1 : ens- efs = zipWith mkEdges ens' (tail ens')- ef = return $ \ as -> concatMap ($as) efs- parseAttrBased EdgeAttribute False ef--instance Functor DotEdge where- fmap f e = e { fromNode = f $ fromNode e- , toNode = f $ toNode e- }--dirEdge :: String-dirEdge = "->"--dirEdge' :: DotCode-dirEdge' = text $ T.pack dirEdge--undirEdge :: String-undirEdge = "--"--undirEdge' :: DotCode-undirEdge' = text $ T.pack undirEdge---- -------------------------------------------------------------------------------- Labels--dirGraph :: String-dirGraph = "digraph"--dirGraph' :: DotCode-dirGraph' = text $ T.pack dirGraph--undirGraph :: String-undirGraph = "graph"--undirGraph' :: DotCode-undirGraph' = text $ T.pack undirGraph--strGraph :: String-strGraph = "strict"--strGraph' :: DotCode-strGraph' = text $ T.pack strGraph--sGraph :: String-sGraph = "subgraph"--sGraph' :: DotCode-sGraph' = text $ T.pack sGraph--clust :: String-clust = "cluster"--clust' :: DotCode-clust' = text $ T.pack clust---- -------------------------------------------------------------------------------printGraphID :: (a -> Bool) -> (a -> Bool)- -> (a -> Maybe GraphID)- -> a -> DotCode-printGraphID str isDir mID g = do setDirectedness isDir'- bool empty strGraph' (str g)- <+> bool undirGraph' dirGraph' isDir'- <+> maybe empty toDot (mID g)- where- isDir' = isDir g--parseGraphID :: (Bool -> Bool -> Maybe GraphID -> a) -> Parse a-parseGraphID f = do whitespace- str <- isJust <$> optional (parseAndSpace $ string strGraph)- dir <- parseAndSpace ( stringRep True dirGraph- `onFail`- stringRep False undirGraph- )- setDirectedness dir- gID <- optional $ parseAndSpace parse- return $ f str dir gID--printStmtBased :: (a -> DotCode) -> (a -> AttributeType)- -> (a -> stmts) -> (stmts -> DotCode)- -> a -> DotCode-printStmtBased f ftp r dr a = do gs <- getsGS id- setAttributeType $ ftp a- dc <- printBracesBased (f a) (dr $ r a)- modifyGS (const gs)- return dc--printStmtBasedList :: (a -> DotCode) -> (a -> AttributeType)- -> (a -> stmts) -> (stmts -> DotCode)- -> [a] -> DotCode-printStmtBasedList f ftp r dr = vcat . mapM (printStmtBased f ftp r dr)---- Can't use the 'braces' combinator here because we want the closing--- brace lined up with the h value, which due to indentation might not--- be the case with braces.-printBracesBased :: DotCode -> DotCode -> DotCode-printBracesBased h i = vcat $ sequence [ h <+> lbrace- , ind i- , rbrace- ]- where- ind = indent 4---- | This /must/ only be used for sub-graphs, etc.-parseBracesBased :: AttributeType -> Parse a -> Parse a-parseBracesBased tp p = do gs <- getsGS id- setAttributeType tp- a <- whitespace *> parseBraced (wrapWhitespace p)- modifyGS (const gs)- return a- `adjustErr`- ("Not a valid value wrapped in braces.\n\t"++)--printSubGraphID :: (a -> (Bool, Maybe GraphID)) -> a -> DotCode-printSubGraphID f a = sGraph'- <+> maybe cl dtID mID- where- (isCl, mID) = f a- cl = bool empty clust' isCl- dtID = printSGID isCl---- | Print the actual ID for a 'DotSubGraph'.-printSGID :: Bool -> GraphID -> DotCode-printSGID isCl sID = bool noClust addClust isCl- where- noClust = toDot sID- -- Have to manually render it as we need the un-quoted form.- addClust = toDot . T.append (T.pack clust) . T.cons '_'- . renderDot $ mkDot sID- mkDot (Str str) = text str -- Quotes will be escaped later- mkDot gid = unqtDot gid--parseSubGraph :: (Bool -> Maybe GraphID -> stmt -> c) -> Parse stmt -> Parse c-parseSubGraph pid pst = do (isC, fID) <- parseSubGraphID pid- let tp = bool SubGraphAttribute ClusterAttribute isC- fID <$> parseBracesBased tp pst--parseSubGraphID :: (Bool -> Maybe GraphID -> c) -> Parse (Bool,c)-parseSubGraphID f = appl <$> (string sGraph *> whitespace1 *> parseSGID)- where- appl (isC, mid) = (isC, f isC mid)--parseSGID :: Parse (Bool, Maybe GraphID)-parseSGID = oneOf [ getClustFrom <$> parseAndSpace parse- , return (False, Nothing)- ]- where- -- If it's a String value, check to see if it's actually a- -- cluster_Blah value; thus need to manually re-parse it.- getClustFrom (Str str) = runParser' pStr str- getClustFrom gid = (False, Just gid)-- checkCl = stringRep True clust- pStr = do isCl <- checkCl- `onFail`- return False- when isCl $ optional (character '_') *> return ()- sID <- optional pID- let sID' = if sID == emptyID- then Nothing- else sID- return (isCl, sID')-- emptyID = Just $ Str ""-- -- For Strings, there are no more quotes to unescape, so consume- -- what you can.- pID = stringNum <$> manySatisfy (const True)--{- This is a much nicer definition, but unfortunately it doesn't work.- The problem is that Graphviz decides that a subgraph is a cluster- if the ID starts with "cluster" (no quotes); thus, we _have_ to do- the double layer of parsing to get it to work :@-- do isCl <- stringRep True clust- `onFail`- return False- sID <- optional $ do when isCl- $ optional (character '_') *> return ()- parseUnqt- when (isCl || isJust sID) $ whitespace1 *> return ()- return (isCl, sID)--}---- The Bool is True for global, False for local.-printAttrBased :: Bool -> (a -> DotCode) -> (a -> Maybe AttributeType)- -> (a -> Attributes) -> a -> DotCode-printAttrBased prEmp ff ftp fas a = do oldType <- getAttributeType- maybe (return ()) setAttributeType mtp- oldCS <- getColorScheme- (dc <> semi) <* unless prEmp (setColorScheme oldCS)- <* setAttributeType oldType- where- mtp = ftp a- f = ff a- dc = case fas a of- [] | not prEmp -> f- as -> f <+> toDot as---- The Bool is True for global, False for local.-printAttrBasedList :: Bool -> (a -> DotCode) -> (a -> Maybe AttributeType)- -> (a -> Attributes) -> [a] -> DotCode-printAttrBasedList prEmp ff ftp fas = vcat . mapM (printAttrBased prEmp ff ftp fas)---- The Bool is True for global, False for local.-parseAttrBased :: AttributeType -> Bool -> Parse (Attributes -> a) -> Parse a-parseAttrBased tp lc p = do oldType <- getAttributeType- setAttributeType tp- oldCS <- getColorScheme- f <- p- atts <- tryParseList' (whitespace *> parse)- unless lc $ setColorScheme oldCS- when (tp /= oldType) $ setAttributeType oldType- return $ f atts- `adjustErr`- ("Not a valid attribute-based structure\n\t"++)---- The Bool is True for global, False for local.-parseAttrBasedList :: AttributeType -> Bool -> Parse (Attributes -> a) -> Parse [a]-parseAttrBasedList tp lc = parseStatements . parseAttrBased tp lc---- | Parse the separator (and any other whitespace1 present) between statements.-statementEnd :: Parse ()-statementEnd = parseSplit *> newline'- where- parseSplit = (whitespace *> oneOf [ character ';' *> return ()- , newline- ]- )- `onFail`- whitespace1--parseStatements :: Parse a -> Parse [a]-parseStatements p = sepBy (whitespace *> p) statementEnd- `discard`- optional statementEnd
Data/GraphViz/Types/Generalised.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} {- | Module : Data.GraphViz.Types.Generalised.@@ -49,6 +49,7 @@ -} module Data.GraphViz.Types.Generalised ( DotGraph(..)+ , FromGeneralisedDot (..) -- * Sub-components of a @DotGraph@. , DotStatements , DotStatement(..)@@ -60,21 +61,23 @@ , DotEdge(..) ) where -import Data.GraphViz.Types-import qualified Data.GraphViz.Types.Canonical as C-import Data.GraphViz.Types.Common-import Data.GraphViz.Types.State-import Data.GraphViz.Parsing-import Data.GraphViz.Printing-import Data.GraphViz.State(AttributeType(..))-import Data.GraphViz.Util(bool)+import Data.GraphViz.Algorithms (canonicalise)+import Data.GraphViz.Internal.State (AttributeType (..))+import Data.GraphViz.Internal.Util (bool)+import Data.GraphViz.Parsing+import Data.GraphViz.Printing+import Data.GraphViz.Types+import qualified Data.GraphViz.Types.Canonical as C+import Data.GraphViz.Types.Internal.Common+import Data.GraphViz.Types.State -import qualified Data.Sequence as Seq-import Data.Sequence(Seq, (><))-import qualified Data.Foldable as F-import qualified Data.Traversable as T-import Control.Arrow((&&&))-import Control.Monad.Trans.State(get, put, modify, execState, evalState)+import Control.Arrow ((&&&))+import Control.Monad.Trans.State (evalState, execState, get, modify,+ put)+import qualified Data.Foldable as F+import Data.Sequence (Seq, (><))+import qualified Data.Sequence as Seq+import qualified Data.Traversable as T -- ----------------------------------------------------------------------------- @@ -150,6 +153,22 @@ -- ----------------------------------------------------------------------------- +-- | This class is useful for being able to parse in a dot graph as a+-- generalised one, and then convert it to your preferred+-- representation.+--+-- This can be seen as a semi-inverse of 'fromCanonical'.+class (DotRepr dg n) => FromGeneralisedDot dg n where+ fromGeneralised :: DotGraph n -> dg n++instance (Ord n) => FromGeneralisedDot C.DotGraph n where+ fromGeneralised = canonicalise++instance (Ord n) => FromGeneralisedDot DotGraph n where+ fromGeneralised = id++-- -----------------------------------------------------------------------------+ type DotStatements n = Seq (DotStatement n) printGStmts :: (PrintDot n) => DotStatements n -> DotCode@@ -307,7 +326,7 @@ sgRe sg = do sgid' <- case subGraphID sg of Nothing -> do n <- get put $ succ n- return . Just $ Int n+ return . Just . Num $ Int n sgid -> return sgid stmts' <- stsRe $ subGraphStmts sg return $ sg { subGraphID = sgid'
Data/GraphViz/Types/Graph.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} {- | Module : Data.GraphViz.Types.Graph@@ -96,28 +96,31 @@ , removeEmptyClusters ) where -import Data.GraphViz.Types-import qualified Data.GraphViz.Types.Canonical as C-import qualified Data.GraphViz.Types.Generalised as G-import Data.GraphViz.Types.Common(partitionGlobal)-import qualified Data.GraphViz.Types.State as St-import Data.GraphViz.Attributes.Same-import Data.GraphViz.Attributes.Complete(Attributes)-import Data.GraphViz.Util(groupSortBy, groupSortCollectBy)-import Data.GraphViz.Algorithms(CanonicaliseOptions(..), canonicaliseOptions)-import Data.GraphViz.Algorithms.Clustering+import Data.GraphViz.Algorithms (CanonicaliseOptions (..),+ canonicaliseOptions)+import Data.GraphViz.Algorithms.Clustering+import Data.GraphViz.Attributes.Complete (Attributes)+import Data.GraphViz.Attributes.Same+import Data.GraphViz.Internal.Util (groupSortBy,+ groupSortCollectBy)+import Data.GraphViz.Types+import qualified Data.GraphViz.Types.Canonical as C+import qualified Data.GraphViz.Types.Generalised as G+import Data.GraphViz.Types.Internal.Common (partitionGlobal)+import qualified Data.GraphViz.Types.State as St -import Data.List(foldl', delete, unfoldr)-import qualified Data.Foldable as F-import Data.Maybe(mapMaybe, fromMaybe)-import qualified Data.Map as M-import Data.Map(Map)-import qualified Data.Set as S-import qualified Data.Sequence as Seq-import Control.Applicative(liftA2, (<$>), (<*>))-import Control.Arrow((***))-import Text.Read(Lexeme(Ident), lexP, parens, readPrec)-import Text.ParserCombinators.ReadPrec(prec)+import Control.Applicative (liftA2, (<$>), (<*>))+import Control.Arrow ((***))+import qualified Data.Foldable as F+import Data.List (delete, foldl', unfoldr)+import Data.Map (Map)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, mapMaybe)+import qualified Data.Sequence as Seq+import qualified Data.Set as S+import Text.ParserCombinators.ReadPrec (prec)+import Text.Read (Lexeme (Ident), lexP, parens,+ readPrec) -- ----------------------------------------------------------------------------- @@ -564,6 +567,9 @@ edgeInformation = getEdgeInfo unAnonymise = id -- No anonymous clusters!++instance (Ord n) => G.FromGeneralisedDot DotGraph n where+ fromGeneralised = fromDotRepr instance (Ord n, PrintDot n) => PrintDotRepr DotGraph n instance (Ord n, ParseDot n) => ParseDotRepr DotGraph n
+ Data/GraphViz/Types/Internal/Common.hs view
@@ -0,0 +1,547 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}++{- |+ Module : Data.GraphViz.Types.Internal.Common+ Description : Common internal functions for dealing with overall types.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module provides common functions used by both+ "Data.GraphViz.Types" as well as "Data.GraphViz.Types.Generalised".+-}+module Data.GraphViz.Types.Internal.Common+ ( GraphID (..)+ , Number (..)+ , numericValue+ , GlobalAttributes (..)+ , partitionGlobal+ , unPartitionGlobal+ , withGlob+ , DotNode (..)+ , DotEdge (..)+ , parseEdgeLine+ , printGraphID+ , parseGraphID+ , printStmtBased+ , printStmtBasedList+ , printSubGraphID+ , parseSubGraph+ , parseBracesBased+ , parseStatements+ ) where++import Data.GraphViz.Attributes.Complete (Attribute (HeadPort, TailPort),+ Attributes, Number (..),+ usedByClusters, usedByGraphs,+ usedByNodes)+import Data.GraphViz.Attributes.Internal (PortPos, parseEdgeBasedPP)+import Data.GraphViz.Internal.State+import Data.GraphViz.Internal.Util+import Data.GraphViz.Parsing+import Data.GraphViz.Printing++import Control.Monad (unless, when)+import Data.Maybe (isJust)+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.Read as T++-- -----------------------------------------------------------------------------+-- This is re-exported by Data.GraphViz.Types++-- | A polymorphic type that covers all possible ID values allowed by+-- Dot syntax. Note that whilst the 'ParseDot' and 'PrintDot'+-- instances for 'String' will properly take care of the special+-- cases for numbers, they are treated differently here.+data GraphID = Str Text+ | Num Number+ deriving (Eq, Ord, Show, Read)++instance PrintDot GraphID where+ unqtDot (Str str) = unqtDot str+ unqtDot (Num n) = unqtDot n++ toDot (Str str) = toDot str+ toDot (Num n) = toDot n++instance ParseDot GraphID where+ parseUnqt = stringNum <$> parseUnqt++ parse = stringNum <$> parse+ `adjustErr`+ ("Not a valid GraphID\n\t"++)++stringNum :: Text -> GraphID+stringNum str = maybe checkDbl (Num . Int) $ stringToInt str+ where+ checkDbl = if isNumString str+ then Num . Dbl $ toDouble str+ else Str str++numericValue :: GraphID -> Maybe Int+numericValue (Str str) = either (const Nothing) (Just . round . fst)+ $ T.signed T.double str+numericValue (Num n) = case n of+ Int i -> Just i+ Dbl d -> Just $ round d++-- -----------------------------------------------------------------------------++-- Re-exported by Data.GraphViz.Types.*++-- | Represents a list of top-level list of 'Attribute's for the+-- entire graph/sub-graph. Note that 'GraphAttrs' also applies to+-- 'DotSubGraph's.+--+-- Note that Dot allows a single 'Attribute' to be listed on a line;+-- if this is the case then when parsing, the type of 'Attribute' it+-- is determined and that type of 'GlobalAttribute' is created.+data GlobalAttributes = GraphAttrs { attrs :: Attributes }+ | NodeAttrs { attrs :: Attributes }+ | EdgeAttrs { attrs :: Attributes }+ deriving (Eq, Ord, Show, Read)++instance PrintDot GlobalAttributes where+ unqtDot = printAttrBased True printGlobAttrType globAttrType attrs++ unqtListToDot = printAttrBasedList True printGlobAttrType globAttrType attrs++ listToDot = unqtListToDot++-- GraphAttrs, NodeAttrs and EdgeAttrs respectively+partitionGlobal :: [GlobalAttributes] -> (Attributes, Attributes, Attributes)+partitionGlobal = foldr select ([], [], [])+ where+ select globA ~(gs,ns,es) = case globA of+ GraphAttrs as -> (as ++ gs, ns, es)+ NodeAttrs as -> (gs, as ++ ns, es)+ EdgeAttrs as -> (gs, ns, as ++ es)++unPartitionGlobal :: (Attributes, Attributes, Attributes) -> [GlobalAttributes]+unPartitionGlobal (gas,nas,eas) = [ GraphAttrs gas+ , NodeAttrs nas+ , EdgeAttrs eas+ ]++printGlobAttrType :: GlobalAttributes -> DotCode+printGlobAttrType GraphAttrs{} = text "graph"+printGlobAttrType NodeAttrs{} = text "node"+printGlobAttrType EdgeAttrs{} = text "edge"++instance ParseDot GlobalAttributes where+ -- Not using parseAttrBased here because we want to force usage of+ -- Attributes.+ parseUnqt = do gat <- parseGlobAttrType++ -- Determine if we need to set the attribute type.+ let mtp = globAttrType $ gat [] -- Only need the constructor+ oldTp <- getAttributeType+ maybe (return ()) setAttributeType mtp++ as <- whitespace *> parse++ -- Safe to set back even if not changed.+ setAttributeType oldTp+ return $ gat as+ `onFail`+ fmap determineType parse++ parse = parseUnqt -- Don't want the option of quoting+ `adjustErr`+ ("Not a valid listing of global attributes\n\t"++)++ -- Have to do this manually because of the special case+ parseUnqtList = parseStatements parseUnqt++ parseList = parseUnqtList++-- Cheat: rather than determine whether it's a graph, cluster or+-- sub-graph just don't set it.+globAttrType :: GlobalAttributes -> Maybe AttributeType+globAttrType NodeAttrs{} = Just NodeAttribute+globAttrType EdgeAttrs{} = Just EdgeAttribute+globAttrType _ = Nothing++parseGlobAttrType :: Parse (Attributes -> GlobalAttributes)+parseGlobAttrType = oneOf [ stringRep GraphAttrs "graph"+ , stringRep NodeAttrs "node"+ , stringRep EdgeAttrs "edge"+ ]++determineType :: Attribute -> GlobalAttributes+determineType attr+ | usedByGraphs attr = GraphAttrs attr'+ | usedByClusters attr = GraphAttrs attr' -- Also covers SubGraph case+ | usedByNodes attr = NodeAttrs attr'+ | otherwise = EdgeAttrs attr' -- Must be for edges.+ where+ attr' = [attr]++withGlob :: (Attributes -> Attributes) -> GlobalAttributes -> GlobalAttributes+withGlob f (GraphAttrs as) = GraphAttrs $ f as+withGlob f (NodeAttrs as) = NodeAttrs $ f as+withGlob f (EdgeAttrs as) = EdgeAttrs $ f as++-- -----------------------------------------------------------------------------++-- | A node in 'DotGraph'.+data DotNode n = DotNode { nodeID :: n+ , nodeAttributes :: Attributes+ }+ deriving (Eq, Ord, Show, Read)++instance (PrintDot n) => PrintDot (DotNode n) where+ unqtDot = printAttrBased False printNodeID+ (const $ Just NodeAttribute) nodeAttributes++ unqtListToDot = printAttrBasedList False printNodeID+ (const $ Just NodeAttribute) nodeAttributes++ listToDot = unqtListToDot++printNodeID :: (PrintDot n) => DotNode n -> DotCode+printNodeID = toDot . nodeID++instance (ParseDot n) => ParseDot (DotNode n) where+ parseUnqt = parseAttrBased NodeAttribute False parseNodeID++ parse = parseUnqt -- Don't want the option of quoting++ parseUnqtList = parseAttrBasedList NodeAttribute False parseNodeID++ parseList = parseUnqtList++parseNodeID :: (ParseDot n) => Parse (Attributes -> DotNode n)+parseNodeID = DotNode <$> parseAndCheck+ where+ parseAndCheck = do n <- parse+ me <- optional parseUnwanted+ maybe (return n) (const notANode) me+ notANode = fail "This appears to be an edge, not a node"+ parseUnwanted = oneOf [ parseEdgeType *> return ()+ , character ':' *> return () -- PortPos value+ ]++instance Functor DotNode where+ fmap f n = n { nodeID = f $ nodeID n }++-- -----------------------------------------------------------------------------++-- This is re-exported in Data.GraphViz.Types; defined here so that+-- Generalised can access and use parseEdgeLine (needed for "a -> b ->+-- c"-style edge statements).++-- | An edge in 'DotGraph'.+data DotEdge n = DotEdge { fromNode :: n+ , toNode :: n+ , edgeAttributes :: Attributes+ }+ deriving (Eq, Ord, Show, Read)++instance (PrintDot n) => PrintDot (DotEdge n) where+ unqtDot = printAttrBased False printEdgeID+ (const $ Just EdgeAttribute) edgeAttributes++ unqtListToDot = printAttrBasedList False printEdgeID+ (const $ Just EdgeAttribute) edgeAttributes++ listToDot = unqtListToDot++printEdgeID :: (PrintDot n) => DotEdge n -> DotCode+printEdgeID e = do isDir <- getDirectedness+ toDot (fromNode e)+ <+> bool undirEdge' dirEdge' isDir+ <+> toDot (toNode e)+++instance (ParseDot n) => ParseDot (DotEdge n) where+ parseUnqt = parseAttrBased EdgeAttribute False parseEdgeID++ parse = parseUnqt -- Don't want the option of quoting++ -- Have to take into account edges of the type "n1 -> n2 -> n3", etc.+ parseUnqtList = concat <$> parseStatements parseEdgeLine++ parseList = parseUnqtList++parseEdgeID :: (ParseDot n) => Parse (Attributes -> DotEdge n)+parseEdgeID = ignoreSep mkEdge parseEdgeNode parseEdgeType parseEdgeNode+ `adjustErr`+ ("Parsed beginning of DotEdge but could not parse Attributes:\n\t"++)+ -- Parse both edge types just to be more liberal++type EdgeNode n = (n, Maybe PortPos)++-- | Takes into account edge statements containing something like+-- @a -> \{b c\}@.+parseEdgeNodes :: (ParseDot n) => Parse [EdgeNode n]+parseEdgeNodes = parseBraced ( wrapWhitespace+ -- Should really use sepBy1, but this will do.+ $ parseStatements parseEdgeNode+ )+ `onFail`+ fmap (:[]) parseEdgeNode++parseEdgeNode :: (ParseDot n) => Parse (EdgeNode n)+parseEdgeNode = liftA2 (,) parse+ (optional $ character ':' *> parseEdgeBasedPP)++mkEdge :: EdgeNode n -> EdgeNode n -> Attributes -> DotEdge n+mkEdge (eFrom, mFP) (eTo, mTP) = DotEdge eFrom eTo+ . addPortPos TailPort mFP+ . addPortPos HeadPort mTP++mkEdges :: [EdgeNode n] -> [EdgeNode n]+ -> Attributes -> [DotEdge n]+mkEdges fs ts as = liftA2 (\f t -> mkEdge f t as) fs ts++addPortPos :: (PortPos -> Attribute) -> Maybe PortPos+ -> Attributes -> Attributes+addPortPos c = maybe id ((:) . c)++parseEdgeType :: Parse Bool+parseEdgeType = wrapWhitespace $ stringRep True dirEdge+ `onFail`+ stringRep False undirEdge++parseEdgeLine :: (ParseDot n) => Parse [DotEdge n]+parseEdgeLine = do n1 <- parseEdgeNodes+ ens <- many1 $ parseEdgeType *> parseEdgeNodes+ let ens' = n1 : ens+ efs = zipWith mkEdges ens' (tail ens')+ ef = return $ \ as -> concatMap ($as) efs+ parseAttrBased EdgeAttribute False ef++instance Functor DotEdge where+ fmap f e = e { fromNode = f $ fromNode e+ , toNode = f $ toNode e+ }++dirEdge :: String+dirEdge = "->"++dirEdge' :: DotCode+dirEdge' = text $ T.pack dirEdge++undirEdge :: String+undirEdge = "--"++undirEdge' :: DotCode+undirEdge' = text $ T.pack undirEdge++-- -----------------------------------------------------------------------------+-- Labels++dirGraph :: String+dirGraph = "digraph"++dirGraph' :: DotCode+dirGraph' = text $ T.pack dirGraph++undirGraph :: String+undirGraph = "graph"++undirGraph' :: DotCode+undirGraph' = text $ T.pack undirGraph++strGraph :: String+strGraph = "strict"++strGraph' :: DotCode+strGraph' = text $ T.pack strGraph++sGraph :: String+sGraph = "subgraph"++sGraph' :: DotCode+sGraph' = text $ T.pack sGraph++clust :: String+clust = "cluster"++clust' :: DotCode+clust' = text $ T.pack clust++-- -----------------------------------------------------------------------------++printGraphID :: (a -> Bool) -> (a -> Bool)+ -> (a -> Maybe GraphID)+ -> a -> DotCode+printGraphID str isDir mID g = do setDirectedness isDir'+ bool empty strGraph' (str g)+ <+> bool undirGraph' dirGraph' isDir'+ <+> maybe empty toDot (mID g)+ where+ isDir' = isDir g++parseGraphID :: (Bool -> Bool -> Maybe GraphID -> a) -> Parse a+parseGraphID f = do whitespace+ str <- isJust <$> optional (parseAndSpace $ string strGraph)+ dir <- parseAndSpace ( stringRep True dirGraph+ `onFail`+ stringRep False undirGraph+ )+ setDirectedness dir+ gID <- optional $ parseAndSpace parse+ return $ f str dir gID++printStmtBased :: (a -> DotCode) -> (a -> AttributeType)+ -> (a -> stmts) -> (stmts -> DotCode)+ -> a -> DotCode+printStmtBased f ftp r dr a = do gs <- getsGS id+ setAttributeType $ ftp a+ dc <- printBracesBased (f a) (dr $ r a)+ modifyGS (const gs)+ return dc++printStmtBasedList :: (a -> DotCode) -> (a -> AttributeType)+ -> (a -> stmts) -> (stmts -> DotCode)+ -> [a] -> DotCode+printStmtBasedList f ftp r dr = vcat . mapM (printStmtBased f ftp r dr)++-- Can't use the 'braces' combinator here because we want the closing+-- brace lined up with the h value, which due to indentation might not+-- be the case with braces.+printBracesBased :: DotCode -> DotCode -> DotCode+printBracesBased h i = vcat $ sequence [ h <+> lbrace+ , ind i+ , rbrace+ ]+ where+ ind = indent 4++-- | This /must/ only be used for sub-graphs, etc.+parseBracesBased :: AttributeType -> Parse a -> Parse a+parseBracesBased tp p = do gs <- getsGS id+ setAttributeType tp+ a <- whitespace *> parseBraced (wrapWhitespace p)+ modifyGS (const gs)+ return a+ `adjustErr`+ ("Not a valid value wrapped in braces.\n\t"++)++printSubGraphID :: (a -> (Bool, Maybe GraphID)) -> a -> DotCode+printSubGraphID f a = sGraph'+ <+> maybe cl dtID mID+ where+ (isCl, mID) = f a+ cl = bool empty clust' isCl+ dtID = printSGID isCl++-- | Print the actual ID for a 'DotSubGraph'.+printSGID :: Bool -> GraphID -> DotCode+printSGID isCl sID = bool noClust addClust isCl+ where+ noClust = toDot sID+ -- Have to manually render it as we need the un-quoted form.+ addClust = toDot . T.append (T.pack clust) . T.cons '_'+ . renderDot $ mkDot sID+ mkDot (Str str) = text str -- Quotes will be escaped later+ mkDot gid = unqtDot gid++parseSubGraph :: (Bool -> Maybe GraphID -> stmt -> c) -> Parse stmt -> Parse c+parseSubGraph pid pst = do (isC, fID) <- parseSubGraphID pid+ let tp = bool SubGraphAttribute ClusterAttribute isC+ fID <$> parseBracesBased tp pst++parseSubGraphID :: (Bool -> Maybe GraphID -> c) -> Parse (Bool,c)+parseSubGraphID f = appl <$> (string sGraph *> whitespace1 *> parseSGID)+ where+ appl (isC, mid) = (isC, f isC mid)++parseSGID :: Parse (Bool, Maybe GraphID)+parseSGID = oneOf [ getClustFrom <$> parseAndSpace parse+ , return (False, Nothing)+ ]+ where+ -- If it's a String value, check to see if it's actually a+ -- cluster_Blah value; thus need to manually re-parse it.+ getClustFrom (Str str) = runParser' pStr str+ getClustFrom gid = (False, Just gid)++ checkCl = stringRep True clust+ pStr = do isCl <- checkCl+ `onFail`+ return False+ when isCl $ optional (character '_') *> return ()+ sID <- optional pID+ let sID' = if sID == emptyID+ then Nothing+ else sID+ return (isCl, sID')++ emptyID = Just $ Str ""++ -- For Strings, there are no more quotes to unescape, so consume+ -- what you can.+ pID = stringNum <$> manySatisfy (const True)++{- This is a much nicer definition, but unfortunately it doesn't work.+ The problem is that Graphviz decides that a subgraph is a cluster+ if the ID starts with "cluster" (no quotes); thus, we _have_ to do+ the double layer of parsing to get it to work :@++ do isCl <- stringRep True clust+ `onFail`+ return False+ sID <- optional $ do when isCl+ $ optional (character '_') *> return ()+ parseUnqt+ when (isCl || isJust sID) $ whitespace1 *> return ()+ return (isCl, sID)+-}++-- The Bool is True for global, False for local.+printAttrBased :: Bool -> (a -> DotCode) -> (a -> Maybe AttributeType)+ -> (a -> Attributes) -> a -> DotCode+printAttrBased prEmp ff ftp fas a = do oldType <- getAttributeType+ maybe (return ()) setAttributeType mtp+ oldCS <- getColorScheme+ (dc <> semi) <* unless prEmp (setColorScheme oldCS)+ <* setAttributeType oldType+ where+ mtp = ftp a+ f = ff a+ dc = case fas a of+ [] | not prEmp -> f+ as -> f <+> toDot as++-- The Bool is True for global, False for local.+printAttrBasedList :: Bool -> (a -> DotCode) -> (a -> Maybe AttributeType)+ -> (a -> Attributes) -> [a] -> DotCode+printAttrBasedList prEmp ff ftp fas = vcat . mapM (printAttrBased prEmp ff ftp fas)++-- The Bool is True for global, False for local.+parseAttrBased :: AttributeType -> Bool -> Parse (Attributes -> a) -> Parse a+parseAttrBased tp lc p = do oldType <- getAttributeType+ setAttributeType tp+ oldCS <- getColorScheme+ f <- p+ atts <- tryParseList' (whitespace *> parse)+ unless lc $ setColorScheme oldCS+ when (tp /= oldType) $ setAttributeType oldType+ return $ f atts+ `adjustErr`+ ("Not a valid attribute-based structure\n\t"++)++-- The Bool is True for global, False for local.+parseAttrBasedList :: AttributeType -> Bool -> Parse (Attributes -> a) -> Parse [a]+parseAttrBasedList tp lc = parseStatements . parseAttrBased tp lc++-- | Parse the separator (and any other whitespace1 present) between statements.+statementEnd :: Parse ()+statementEnd = parseSplit *> newline'+ where+ parseSplit = (whitespace *> oneOf [ character ';' *> return ()+ , newline+ ]+ )+ `onFail`+ whitespace1++parseStatements :: Parse a -> Parse [a]+parseStatements p = sepBy (whitespace *> p) statementEnd+ `discard`+ optional statementEnd
Data/GraphViz/Types/Monadic.hs view
@@ -75,13 +75,13 @@ , (<->) ) where -import Data.GraphViz.Attributes(Attributes)-import Data.GraphViz.Types.Common+import Data.GraphViz.Attributes (Attributes) import Data.GraphViz.Types.Generalised -import qualified Data.DList as DL-import Data.DList(DList)-import qualified Data.Sequence as Seq+import Control.Applicative (Applicative (..))+import Data.DList (DList)+import qualified Data.DList as DL+import qualified Data.Sequence as Seq -- ----------------------------------------------------------------------------- -- The Dot monad.@@ -97,8 +97,16 @@ execDot :: DotM n a -> DotStmts n execDot = snd . runDot +instance Functor (DotM n) where+ fmap f (DotM (a,stmts)) = DotM (f a, stmts)++instance Applicative (DotM n) where+ pure = DotM . flip (,) DL.empty++ (DotM (f,stmts1)) <*> (DotM (a,stmts2)) = DotM (f a, stmts1 `DL.append` stmts2)+ instance Monad (DotM n) where- return a = DotM (a, DL.empty)+ return = pure dt >>= f = DotM $ let ~(a,stmts) = runDot dt
Data/GraphViz/Types/State.hs view
@@ -34,22 +34,22 @@ , addEdge ) where -import Data.GraphViz.Types.Common-import Data.GraphViz.Attributes.Complete( Attributes- , usedByClusters, usedByGraphs)+import Data.GraphViz.Attributes.Complete (Attributes, usedByClusters,+ usedByGraphs) import Data.GraphViz.Attributes.Same+import Data.GraphViz.Types.Internal.Common -import Data.Function(on)-import qualified Data.DList as DList-import Data.DList(DList)-import qualified Data.Map as Map-import Data.Map(Map)-import qualified Data.Set as Set-import qualified Data.Sequence as Seq-import Data.Sequence(Seq, (|>), ViewL(..))-import Control.Arrow((&&&), (***))-import Control.Monad(when)-import Control.Monad.Trans.State+import Control.Arrow ((&&&), (***))+import Control.Monad (when)+import Control.Monad.Trans.State+import Data.DList (DList)+import qualified Data.DList as DList+import Data.Function (on)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Sequence (Seq, ViewL (..), (|>))+import qualified Data.Sequence as Seq+import qualified Data.Set as Set -- ----------------------------------------------------------------------------- @@ -160,8 +160,8 @@ type NodeLookup' n = Map n NodeInfo -data NodeInfo = NI { atts :: SAttrs- , gAtts :: SAttrs -- from globals+data NodeInfo = NI { atts :: SAttrs+ , gAtts :: SAttrs -- from globals , location :: Path } deriving (Eq, Ord, Show, Read)
− Data/GraphViz/Util.hs
@@ -1,165 +0,0 @@-{-# LANGUAGE OverloadedStrings, PatternGuards #-}-{-# OPTIONS_HADDOCK hide #-}--{- |- Module : Data.GraphViz.Util- Description : Internal utility functions- Copyright : (c) Ivan Lazar Miljenovic- License : 3-Clause BSD-style- Maintainer : Ivan.Miljenovic@gmail.com-- This module defines internal utility functions.--}-module Data.GraphViz.Util where--import Data.Char( isAsciiUpper- , isAsciiLower- , isDigit- , ord- )--import Data.List(groupBy, sortBy)-import Data.Maybe(isJust)-import Data.Function(on)-import qualified Data.Set as Set-import Data.Set(Set)-import qualified Data.Text.Lazy as T-import qualified Data.Text.Lazy.Read as T-import Data.Text.Lazy(Text)-import Control.Monad(liftM2)---- -------------------------------------------------------------------------------isIDString :: Text -> Bool-isIDString = maybe False (\(f,os) -> frstIDString f && T.all restIDString os)- . T.uncons---- | First character of a non-quoted 'String' must match this.-frstIDString :: Char -> Bool-frstIDString c = any ($c) [ isAsciiUpper- , isAsciiLower- , (==) '_'- , (\ x -> ord x >= 128)- ]---- | The rest of a non-quoted 'String' must match this.-restIDString :: Char -> Bool-restIDString c = frstIDString c || isDigit c---- | Determine if this String represents a number.-isNumString :: Text -> Bool-isNumString "" = False-isNumString "-" = False-isNumString str = case T.uncons $ T.toLower str of- Just ('-',str') -> go str'- _ -> go str- where- -- Can't use Data.Text.Lazy.Read.double as it doesn't cover all- -- possible cases- go s = uncurry go' $ T.span isDigit s- go' ds nds- | T.null nds = True- | T.null ds && nds == "." = False- | T.null ds- , Just ('.',nds') <- T.uncons nds- , Just (d,nds'') <- T.uncons nds' = isDigit d && checkEs' nds''- | Just ('.',nds') <- T.uncons nds = checkEs $ T.dropWhile isDigit nds'- | T.null ds = False- | otherwise = checkEs nds- checkEs' s = case T.break ('e' ==) s of- ("", _) -> False- (ds,es) -> T.all isDigit ds && checkEs es- checkEs str' = case T.uncons str' of- Nothing -> True- Just ('e',ds) -> isIntString ds- _ -> False--{---- | This assumes that 'isNumString' is 'True'.-toDouble :: Text -> Double-toDouble str = case T.uncons $ T.toLower str of- Just ('-', str') -> toD $ '-' `T.cons` adj str'- _ -> toD $ adj str- where- adj s = T.cons '0'- $ case T.span ('.' ==) s of- (ds, ".") | not $ T.null ds -> s `T.snoc` '0'- (ds, ds') | Just ('.',es) <- T.uncons ds'- , Just ('e',es') <- T.uncons es- -> ds `T.snoc` '.' `T.snoc` '0'- `T.snoc` 'e' `T.snoc` '0' `T.append` es'- _ -> s- toD = either (const $ error "Not a Double") fst . T.signed T.double--}--- | This assumes that 'isNumString' is 'True'.-toDouble :: Text -> Double-toDouble str = case T.uncons $ T.toLower str of- Just ('-', str') -> toD $ '-' `T.cons` adj str'- _ -> toD $ adj str- where- adj s = T.cons '0'- $ case T.span ('.' ==) s of- (ds, ".") | not $ T.null ds -> s `T.snoc` '0'- (ds, ds') | Just ('.',es) <- T.uncons ds'- , Just ('e',_) <- T.uncons es- -> ds `T.snoc` '.' `T.snoc` '0' `T.append` es- _ -> s- toD = read . T.unpack--isIntString :: Text -> Bool-isIntString = isJust . stringToInt---- | Determine if this String represents an integer.-stringToInt :: Text -> Maybe Int-stringToInt str = case T.signed T.decimal str of- Right (n, "") -> Just n- _ -> Nothing---- | Graphviz requires double quotes to be explicitly escaped.-escapeQuotes :: String -> String-escapeQuotes [] = []-escapeQuotes ('"':str) = '\\':'"': escapeQuotes str-escapeQuotes (c:str) = c : escapeQuotes str---- | Remove explicit escaping of double quotes.-descapeQuotes :: String -> String-descapeQuotes [] = []-descapeQuotes ('\\':'"':str) = '"' : descapeQuotes str-descapeQuotes (c:str) = c : descapeQuotes str--isKeyword :: Text -> Bool-isKeyword = (`Set.member` keywords) . T.toLower---- | The following are Dot keywords and are not valid as labels, etc. unquoted.-keywords :: Set Text-keywords = Set.fromList [ "node"- , "edge"- , "graph"- , "digraph"- , "subgraph"- , "strict"- ]---- -------------------------------------------------------------------------------uniq :: (Ord a) => [a] -> [a]-uniq = uniqBy id--uniqBy :: (Ord b) => (a -> b) -> [a] -> [a]-uniqBy f = map head . groupSortBy f--groupSortBy :: (Ord b) => (a -> b) -> [a] -> [[a]]-groupSortBy f = groupBy ((==) `on` f) . sortBy (compare `on` f)--groupSortCollectBy :: (Ord b) => (a -> b) -> (a -> c) -> [a] -> [(b,[c])]-groupSortCollectBy f g = map (liftM2 (,) (f . head) (map g)) . groupSortBy f---- | Fold over 'Bool's; first param is for 'False', second for 'True'.-bool :: a -> a -> Bool -> a-bool f t b = if b- then t- else f--isSingle :: [a] -> Bool-isSingle [_] = True-isSingle _ = False
FAQ.md view
@@ -35,10 +35,12 @@ * There are [four different representations] of Dot graphs: - 1. Canonical, which matches the layout of `dot -Tcanon`.+ 1. Canonical, which provides a clean separated definition of a+ Dot graph (that matches the former layout of `dot -Tcanon`). 2. Generalised, which allows statements to be in any order. 3. A graph-based one that allows manipulation of the Dot graph.- 4. A monadic interface for embedding graphs in Haskell.+ 4. A monadic interface for embedding relatively static graphs+ in Haskell. There are also conversion functions between them. @@ -53,7 +55,7 @@ * The ability to use a custom node type for Dot graphs. -* Support for the all five layout algorithm programs and all specified+* Support for all stated layout algorithm programs and all specified [output formats] as well as the ability to use custom programs, etc. [output formats]: http://www.graphviz.org/doc/info/output.html@@ -122,12 +124,15 @@ ability to specify an integer prefix for use with the `fdp` layout tool is not available. -* `pointf` and `point` values have been combined into one datatype; as- such, when constructing values such as `Rect` care should be taken- about which parts of a `Point` are allowed.+* The deprecated `shapefile` attribute is not available; instead, you+ should specify the file on the command line. -* Only polygon-based `shape`s are available.+* The deprecated `z` attribute is not available; use the optional+ third dimension for the `pos` attribute instead. +* Only polygon-based `shape`s are available (i.e. no custom shapes as+ yet).+ * The `charset` attribute is not available as _graphviz_ assumes that all Dot graphs will be in UTF-8 for simplicity; if Latin1-encoded graphs need to be parsed then you shall need to do all I/O for them@@ -303,8 +308,8 @@ **Canonical:** -: matches the output of `dot -Tcanon`. Recommended for use when- converting existing data into Dot (especially with the+: matches the (former) output of `dot -Tcanon`. Recommended for use+ when converting existing data into Dot (especially with the `graphElemsToDot` function in `Data.GraphViz`). **Generalised:**@@ -330,21 +335,20 @@ ### What's the best way to parse Dot code? ### -In both cases below, you should use the `parseDotGraph` function to-parse the Dot code: this is because it will strip out comments and-pre-processor lines and join together split lines (if any of these-remain the parser will fail). Also, if you are not sure what the type-of the nodes are, use either String or else the `GraphID` type as it-explicitly caters for both Strings and numbers (whereas just assuming-it being a String will result in numbers being stored internally as a-String).--If you can, first run `dot -Tcanon` on the Dot code and parse it as a-`DotGraph` value. This is because `DotGraph` types are easier to deal-with.+Use the `parseDotGraph` function (rather than the general parsing+functions that are available) to parse your Dot code: this is will+strip out comments and pre-processor lines and join together split+lines (if any of these remain the parser will fail). Also, if you are+not sure what the type of the nodes are, use either String or else the+`GraphID` type as it explicitly caters for both Strings and numbers+(whereas just assuming it being a String will result in numbers being+stored internally as a String). -If, however, this isn't possible (e.g. it uses an image that isn't in-the current working directory) then use the `GDotGraph` type.+Unless you are very sure of the representation of the Dot code you+have been provided, you should parse in any Dot code as the+`Generalised.DotGraph` type. Afterwards you can use+`FromGeneralisedDot` to convert to whichever representation you+prefer. ### There are too many attributes!!! Which ones should I use? ### @@ -394,10 +398,10 @@ be printed like `"1: Foo"`: ~~~~~~~~~~~~~~~~~~~~ {.haskell}-data MyType = MyType String Int+data MyType = MyType Int String instance PrintDot MyType where- unqtDot (MyType s i) = unqtDot i <> colon <+> unqtDot s+ unqtDot (MyType i s) = unqtDot i <> colon <+> unqtDot s -- We have a space in there, so we need quotes. toDot = doubleQuotes . unqtDot@@ -527,8 +531,8 @@ yet [people didn't like the idea](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064442.html). -The graph-based implementation was added solely so I could write as-(un-yet finished) tutorial, and thought others might find it useful.+The graph-based implementation was added solely so I could write an+(as-yet finished) tutorial, and thought others might find it useful. The monadic implementation came about as an attempt to encourage more people to use _graphviz_ rather than other libraries such as [dotgen], and I thought a nicer way of writing Dot graphs might help (the@@ -592,9 +596,9 @@ `TestParsing.hs` script that comes in the _graphviz_ tarball (but is not installed). Once you have _graphviz_ installed you can just run this script, passing it any files containing Dot graphs you wish to-test. It will attempt to parse each Dot graph as a `GDotGraph`, and-then test to see if the canonicalised form is parseable as a-`DotGraph`.+test. It will attempt to parse each Dot graph as a+`Generalised.DotGraph`, and then test to see if the canonicalised form+is parseable as a `DotGraph`. ### I've found a bug! ###
TODO.md view
@@ -1,6 +1,8 @@ % TODO % Ivan Lazar Miljenovic +* Data.Data.Data instances+ Future Plans for graphviz =========================
graphviz.cabal view
@@ -1,5 +1,5 @@ Name: graphviz-Version: 2999.16.0.0+Version: 2999.17.0.0 Stability: Beta Synopsis: Bindings to Graphviz for graph visualisation. Description: {@@ -45,29 +45,32 @@ README.md FAQ.md utils/AttributeGenerator.hs- utils/TestParsing.hs Source-Repository head Type: darcs Location: http://hub.darcs.net/ivanm/graphviz +Flag test-parsing+ Description: Build a utility to test parsing of available Dot code.+ Default: False+ Library {- Default-Language: Haskell98+ Default-Language: Haskell2010 Build-Depends: base == 4.*, containers, process, directory,- temporary >=1.1 && <1.2,- fgl == 5.4.*,+ temporary >=1.1 && <1.3,+ fgl >= 5.4 && < 5.6, filepath,- polyparse >= 1.7 && < 1.9,+ polyparse == 1.9.*, bytestring >= 0.9 && < 0.11, colour == 2.3.*, transformers >= 0.2 && < 0.4, text, wl-pprint-text >= 1.1.0.0 && < 1.2.0.0,- dlist == 0.5.*+ dlist >= 0.5 && < 0.8 Exposed-Modules: Data.GraphViz Data.GraphViz.Types@@ -90,14 +93,18 @@ Data.GraphViz.Exception Data.GraphViz.Algorithms + Data.GraphViz.Attributes.Internal+ Data.GraphViz.Internal.Util+ Data.GraphViz.Internal.State+ Data.GraphViz.Types.Internal.Common+ Other-Modules: Data.GraphViz.Algorithms.Clustering+ Data.GraphViz.Attributes.Arrows Data.GraphViz.Attributes.ColorScheme- Data.GraphViz.Attributes.Internal Data.GraphViz.Attributes.Same- Data.GraphViz.Types.Common+ Data.GraphViz.Attributes.Values+ Data.GraphViz.Commands.Available Data.GraphViz.Types.State- Data.GraphViz.Util- Data.GraphViz.State if True Ghc-Options: -Wall@@ -109,28 +116,20 @@ } Test-Suite graphviz-testsuite {- Default-Language: Haskell98+ Default-Language: Haskell2010 Type: exitcode-stdio-1.0 -- Versions controlled by library section Build-Depends: base,+ graphviz, containers,- process,- directory,- temporary, fgl, filepath,- polyparse,- bytestring,- colour,- transformers, text,- wl-pprint-text,- dlist,- QuickCheck >= 2.3 && < 2.6+ QuickCheck >= 2.3 && < 2.8 - hs-Source-Dirs: . tests+ hs-Source-Dirs: tests Main-Is: RunTests.hs @@ -156,7 +155,7 @@ } Benchmark graphviz-printparse {- Default-Language: Haskell98+ Default-Language: Haskell2010 Type: exitcode-stdio-1.0 @@ -164,7 +163,7 @@ deepseq, text, graphviz,- criterion >= 0.5 && < 0.7+ criterion >= 0.5 && < 0.9 hs-Source-Dirs: utils @@ -175,6 +174,30 @@ if impl(ghc >= 6.12.1) Ghc-Options: -fno-warn-unused-do-bind++ GHC-Prof-Options: -auto-all -caf-all -rtsopts+}++Executable graphviz-testparsing {+ Default-Language: Haskell2010++ if flag(test-parsing)+ Buildable: True+ else+ Buildable: False++ hs-Source-Dirs: utils++ Main-Is: TestParsing.hs++ Build-Depends: base,+ graphviz,+ bytestring,+ directory,+ filepath,+ text++ Ghc-Options: -O -Wall GHC-Prof-Options: -auto-all -caf-all -rtsopts }
tests/Data/GraphViz/Testing/Instances/Attributes.hs view
@@ -19,23 +19,25 @@ import Data.GraphViz.Testing.Instances.Helpers -import Data.GraphViz.Attributes.Complete-import qualified Data.GraphViz.Attributes.HTML as Html-import Data.GraphViz.Attributes.Colors.Brewer-import Data.GraphViz.Attributes.Colors.X11(X11Color)-import Data.GraphViz.Attributes.Colors.SVG(SVGColor)-import Data.GraphViz.Attributes.Internal(compassLookup)-import Data.GraphViz.State(initialState, layerSep, layerListSep)-import Data.GraphViz.Util(bool)+import Data.GraphViz.Attributes.Colors.Brewer+import Data.GraphViz.Attributes.Colors.SVG (SVGColor)+import Data.GraphViz.Attributes.Colors.X11 (X11Color)+import Data.GraphViz.Attributes.Complete+import qualified Data.GraphViz.Attributes.HTML as Html+import Data.GraphViz.Attributes.Internal (compassLookup)+import Data.GraphViz.Internal.State (initialState,+ layerListSep, layerSep)+import Data.GraphViz.Internal.Util (bool, createVersion) import Test.QuickCheck -import Data.List(nub, delete, groupBy)-import qualified Data.Map as Map-import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)-import Control.Monad(liftM, liftM2, liftM3, liftM4)-import System.FilePath(searchPathSeparator)+import Control.Monad (liftM, liftM2, liftM3, liftM4)+import Data.List (delete, groupBy, nub)+import qualified Data.Map as Map+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Data.Version (Version (..))+import System.FilePath (searchPathSeparator) -- ----------------------------------------------------------------------------- -- Defining Arbitrary instances for Attributes@@ -66,7 +68,7 @@ , liftM ArrowHead arbitrary , liftM ArrowSize arbitrary , liftM ArrowTail arbitrary- , liftM Aspect arbitrary+ , liftM Background arbitrary , liftM BoundingBox arbitrary , liftM BgColor arbList , liftM Center arbitrary@@ -112,6 +114,7 @@ , liftM Image arbitrary , liftM ImagePath arbitrary , liftM ImageScale arbitrary+ , liftM InputScale arbitrary , liftM Label arbitrary , liftM LabelURL arbitrary , liftM LabelScheme arbitrary@@ -158,6 +161,7 @@ , liftM OutputOrder arbitrary , liftM Overlap arbitrary , liftM OverlapScaling arbitrary+ , liftM OverlapShrink arbitrary , liftM Pack arbitrary , liftM PackMode arbitrary , liftM Pad arbitrary@@ -213,6 +217,7 @@ , liftM VoroMargin arbitrary , liftM Weight arbitrary , liftM Width arbitrary+ , liftM XDotVersion arbitrary , liftM XLabel arbitrary , liftM XLP arbitrary , liftM2 UnknownAttribute (suchThat arbIDString validUnknown) arbitrary@@ -225,7 +230,7 @@ shrink (ArrowHead v) = map ArrowHead $ shrink v shrink (ArrowSize v) = map ArrowSize $ shrink v shrink (ArrowTail v) = map ArrowTail $ shrink v- shrink (Aspect v) = map Aspect $ shrink v+ shrink (Background v) = map Background $ shrink v shrink (BoundingBox v) = map BoundingBox $ shrink v shrink (BgColor v) = map BgColor $ nonEmptyShrinks v shrink (Center v) = map Center $ shrink v@@ -271,6 +276,7 @@ shrink (Image v) = map Image $ shrink v shrink (ImagePath v) = map ImagePath $ shrink v shrink (ImageScale v) = map ImageScale $ shrink v+ shrink (InputScale v) = map InputScale $ shrink v shrink (Label v) = map Label $ shrink v shrink (LabelURL v) = map LabelURL $ shrink v shrink (LabelScheme v) = map LabelScheme $ shrink v@@ -317,6 +323,7 @@ shrink (OutputOrder v) = map OutputOrder $ shrink v shrink (Overlap v) = map Overlap $ shrink v shrink (OverlapScaling v) = map OverlapScaling $ shrink v+ shrink (OverlapShrink v) = map OverlapShrink $ shrink v shrink (Pack v) = map Pack $ shrink v shrink (PackMode v) = map PackMode $ shrink v shrink (Pad v) = map Pad $ shrink v@@ -372,6 +379,7 @@ shrink (VoroMargin v) = map VoroMargin $ shrink v shrink (Weight v) = map Weight $ shrink v shrink (Width v) = map Width $ shrink v+ shrink (XDotVersion v) = map XDotVersion $ shrink v shrink (XLabel v) = map XLabel $ shrink v shrink (XLP v) = map XLP $ shrink v shrink (UnknownAttribute a v) = liftM2 UnknownAttribute (liftM (filter validUnknown) shrink a) (shrink v)@@ -399,16 +407,6 @@ instance Arbitrary ArrowSide where arbitrary = arbBounded -instance Arbitrary AspectType where- arbitrary = oneof [ liftM RatioOnly arbitrary- , liftM2 RatioPassCount arbitrary posArbitrary- ]-- shrink (RatioOnly d) = map RatioOnly $ shrink d- shrink (RatioPassCount d i) = do ds <- shrink d- is <- shrink i- return $ RatioPassCount ds is- instance Arbitrary LabelScheme where arbitrary = arbBounded @@ -474,7 +472,7 @@ shrink (StrLabel str) = map StrLabel $ shrink str shrink (HtmlLabel html) = map HtmlLabel $ shrink html- shrink (RecordLabel fs) = map RecordLabel . filter notStr $ shrinkList fs+ shrink (RecordLabel fs) = map RecordLabel . filter notStr $ listShrink fs notStr :: RecordFields -> Bool notStr [FieldLabel{}] = False -- Just in case@@ -499,7 +497,7 @@ shrink (LabelledTarget f l) = [PortName f, FieldLabel l] shrink (PortName f) = map PortName $ shrink f shrink (FieldLabel l) = map FieldLabel $ shrink l- shrink (FlipFields fs) = map FlipFields $ shrinkList fs+ shrink (FlipFields fs) = map FlipFields $ listShrink fs instance Arbitrary Overlap where arbitrary = oneof [ simpleOverlap@@ -998,3 +996,44 @@ notCP :: Text -> Bool notCP = flip Map.notMember compassLookup++instance Arbitrary Number where+ arbitrary = frequency [ (3, liftM Dbl $ suchThat arbitrary notInt)+ , (1, liftM Int arbitrary)+ ]++ shrink (Int i) = map Int $ shrink i+ shrink (Dbl d) = map Dbl $ filter notInt $ shrink d++instance Arbitrary Normalized where+ arbitrary = oneof [ elements [IsNormalized, NotNormalized]+ , liftM NormalizedAngle arbitrary+ ]++ shrink (NormalizedAngle a) = map NormalizedAngle $ shrink a+ shrink _ = []++instance Arbitrary Version where+ arbitrary = liftM (createVersion . map getPositive) arbList++ shrink = map createVersion . nonEmptyShrinks . versionBranch++instance Arbitrary NodeSize where+ arbitrary = arbBounded++{-++As of Graphviz 2.36.0 this was commented out; as such it might come+back, so leave this here in case we need it again.++instance Arbitrary AspectType where+ arbitrary = oneof [ liftM RatioOnly arbitrary+ , liftM2 RatioPassCount arbitrary posArbitrary+ ]++ shrink (RatioOnly d) = map RatioOnly $ shrink d+ shrink (RatioPassCount d i) = do ds <- shrink d+ is <- shrink i+ return $ RatioPassCount ds is++-}
tests/Data/GraphViz/Testing/Instances/Canonical.hs view
@@ -13,12 +13,12 @@ import Data.GraphViz.Testing.Instances.Common import Data.GraphViz.Testing.Instances.Helpers +import Data.GraphViz.Internal.Util (bool) import Data.GraphViz.Types.Canonical-import Data.GraphViz.Util(bool) import Test.QuickCheck -import Control.Monad(liftM2, liftM4)+import Control.Monad (liftM2, liftM4) -- ----------------------------------------------------------------------------- -- Defining Arbitrary instances for the overall types
tests/Data/GraphViz/Testing/Instances/Common.hs view
@@ -17,27 +17,25 @@ import Data.GraphViz.Testing.Instances.Attributes import Data.GraphViz.Testing.Instances.Helpers -import Data.GraphViz.Attributes(Attributes)-import Data.GraphViz.Types.Common( DotNode(..), DotEdge(..)- , GlobalAttributes(..), GraphID(..))-import Data.GraphViz.Algorithms(CanonicaliseOptions(..))+import Data.GraphViz.Algorithms (CanonicaliseOptions (..))+import Data.GraphViz.Attributes (Attributes)+import Data.GraphViz.Types.Internal.Common (DotEdge (..), DotNode (..),+ GlobalAttributes (..), GraphID (..)) import Test.QuickCheck -import Control.Monad(liftM, liftM2, liftM3)+import Control.Monad (liftM, liftM2, liftM3) -- ----------------------------------------------------------------------------- -- Common values instance Arbitrary GraphID where arbitrary = oneof [ liftM Str arbitrary- , liftM Int arbitrary- , liftM Dbl $ suchThat arbitrary notInt+ , liftM Num arbitrary ] shrink (Str s) = map Str $ shrink s- shrink (Int i) = map Int $ shrink i- shrink (Dbl d) = map Dbl $ filter notInt $ shrink d+ shrink (Num n) = map Num $ shrink n instance (Arbitrary n) => Arbitrary (DotNode n) where arbitrary = liftM2 DotNode arbitrary arbNodeAttrs
tests/Data/GraphViz/Testing/Instances/FGL.hs view
@@ -18,12 +18,12 @@ import Test.QuickCheck -import Data.GraphViz.Util(uniq)+import Data.GraphViz.Internal.Util (uniq) -import Data.Graph.Inductive.Graph(Graph, mkGraph, nodes, delNode)-import Data.List(sortBy)-import Data.Function(on)-import Control.Monad(liftM, liftM3)+import Control.Monad (liftM, liftM3)+import Data.Function (on)+import Data.Graph.Inductive.Graph (Graph, delNode, mkGraph, nodes)+import Data.List (sortBy) -- ----------------------------------------------------------------------------- -- Arbitrary instance for FGL graphs.
tests/Data/GraphViz/Testing/Instances/Generalised.hs view
@@ -10,17 +10,17 @@ -} module Data.GraphViz.Testing.Instances.Generalised where -import Data.GraphViz.Testing.Instances.Attributes()+import Data.GraphViz.Testing.Instances.Attributes () import Data.GraphViz.Testing.Instances.Common-import Data.GraphViz.Testing.Instances.Helpers()+import Data.GraphViz.Testing.Instances.Helpers () +import Data.GraphViz.Internal.Util (bool) import Data.GraphViz.Types.Generalised-import Data.GraphViz.Util(bool) import Test.QuickCheck +import Control.Monad (liftM, liftM2, liftM4) import qualified Data.Sequence as Seq-import Control.Monad(liftM, liftM2, liftM4) -- ----------------------------------------------------------------------------- -- Defining Arbitrary instances for the generalised types
tests/Data/GraphViz/Testing/Instances/Helpers.hs view
@@ -11,14 +11,14 @@ -} module Data.GraphViz.Testing.Instances.Helpers where -import Data.GraphViz.Parsing(isNumString)-import Data.GraphViz.State(initialState, layerSep, layerListSep)+import Data.GraphViz.Internal.State (initialState, layerListSep, layerSep)+import Data.GraphViz.Parsing (isNumString) import Test.QuickCheck +import Control.Monad (liftM, liftM2)+import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)-import Control.Monad(liftM, liftM2) -- ----------------------------------------------------------------------------- -- Helper Functions@@ -89,17 +89,17 @@ nonEmptyShrinks = filter (not . null) . shrink nonEmptyShrinks' :: [a] -> [[a]]-nonEmptyShrinks' = filter (not . null) . shrinkList'+nonEmptyShrinks' = filter (not . null) . listShrink' -- Shrink lists with more than one value only by removing values, not -- by shrinking individual items.-shrinkList :: (Arbitrary a) => [a] -> [[a]]-shrinkList [a] = map return $ shrink a-shrinkList as = shrinkList' as+listShrink :: (Arbitrary a) => [a] -> [[a]]+listShrink [a] = map return $ shrink a+listShrink as = listShrink' as -- Just shrink the size.-shrinkList' :: [a] -> [[a]]-shrinkList' as = rm (length as) as+listShrink' :: [a] -> [[a]]+listShrink' as = rm (length as) as where rm 0 _ = [] rm 1 _ = [[]]@@ -125,7 +125,7 @@ shrinkM j = shrink j shrinkL :: (Arbitrary a) => [a] -> [[a]]-shrinkL xs = case shrinkList xs of+shrinkL xs = case listShrink xs of [] -> [xs] xs' -> xs'
tests/Data/GraphViz/Testing/Properties.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses #-} {- | Module : Data.GraphViz.Testing.Properties@@ -11,30 +11,37 @@ -} module Data.GraphViz.Testing.Properties where -import Data.GraphViz( dotizeGraph, graphToDot- , setDirectedness, nonClusteredParams)-import Data.GraphViz.Types( DotRepr(..), PrintDotRepr- , DotNode(..), DotEdge(..), GlobalAttributes(..)- , printDotGraph, graphNodes, graphEdges- , nodeInformationClean, edgeInformationClean)-import Data.GraphViz.Types.Canonical(DotGraph(..), DotStatements(..))+import Data.GraphViz (dotizeGraph, graphToDot,+ nonClusteredParams,+ setDirectedness)+import Data.GraphViz.Algorithms+import Data.GraphViz.Internal.Util (groupSortBy, isSingle)+import Data.GraphViz.Parsing (ParseDot (..), parseIt,+ parseIt')+import Data.GraphViz.PreProcessing (preProcess)+import Data.GraphViz.Printing (PrintDot (..), printIt)+import Data.GraphViz.Types (DotEdge (..), DotNode (..),+ DotRepr (..),+ GlobalAttributes (..),+ PrintDotRepr,+ edgeInformationClean,+ graphEdges, graphNodes,+ nodeInformationClean,+ printDotGraph)+import Data.GraphViz.Types.Canonical (DotGraph (..),+ DotStatements (..)) import qualified Data.GraphViz.Types.Generalised as G-import Data.GraphViz.Printing(PrintDot(..), printIt)-import Data.GraphViz.Parsing(ParseDot(..), parseIt, parseIt')-import Data.GraphViz.PreProcessing(preProcess)-import Data.GraphViz.Util(groupSortBy, isSingle)-import Data.GraphViz.Algorithms import Test.QuickCheck -import Data.Graph.Inductive( Graph, DynGraph- , equal, nmap, emap, labNodes, labEdges, nodes, edges)-import Data.List(nub, sort)-import Data.Function(on)-import qualified Data.Map as Map-import qualified Data.Set as Set-import Data.Text.Lazy(Text)-import Control.Arrow((&&&))+import Control.Arrow ((&&&))+import Data.Function (on)+import Data.Graph.Inductive (DynGraph, Graph, edges, emap, equal,+ labEdges, labNodes, nmap, nodes)+import Data.List (nub, sort)+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Text.Lazy (Text) -- ----------------------------------------------------------------------------- -- The properties to test for
utils/AttributeGenerator.hs view
@@ -467,39 +467,39 @@ attributes :: [Attribute] attributes = [ -- BEGIN RECEIVE ORGTBL Attributes- makeAttr "Damping" ["Damping"] "G" (Dbl) Nothing (Just "0.99") (Just "@0.99@") (Just "@0.0@") (Just "neato only"),- makeAttr "K" ["K"] "GC" (Dbl) Nothing (Just "0.3") (Just "@0.3@") (Just "@0@") (Just "sfdp, fdp only"),+ makeAttr "Damping" ["Damping"] "G" (Dbl) Nothing (Just "0.99") (Just "@0.99@") (Just "@0.0@") (Just "'Neato' only"),+ makeAttr "K" ["K"] "GC" (Dbl) Nothing (Just "0.3") (Just "@0.3@") (Just "@0@") (Just "'Sfdp', 'Fdp' only"), makeAttr "URL" ["URL", "href"] "ENGC" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, postscript, map only"),- makeAttr "Area" ["area"] "NC" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@>0@") (Just "patchwork only, requires Graphviz >= 2.30.0"),+ makeAttr "Area" ["area"] "NC" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@>0@") (Just "'Patchwork' only, requires Graphviz >= 2.30.0"), makeAttr "ArrowHead" ["arrowhead"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing, makeAttr "ArrowSize" ["arrowsize"] "E" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") Nothing, makeAttr "ArrowTail" ["arrowtail"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing,- makeAttr "Aspect" ["aspect"] "G" (Cust "AspectType") Nothing Nothing Nothing Nothing (Just "dot only"),+ makeAttr "Background" ["_background"] "G" (Strng) Nothing (Just "\"\"") (Just "none") Nothing (Just "xdot only"), makeAttr "BoundingBox" ["bb"] "G" (Cust "Rect") Nothing Nothing Nothing Nothing (Just "write only"), makeAttr "BgColor" ["bgcolor"] "GC" (Cust "ColorList") Nothing (Just "[]") (Just "@[]@") Nothing Nothing, makeAttr "Center" ["center"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,- makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "Local") (Just "@'Local'@") Nothing (Just "dot only"),+ makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "Local") (Just "@'Local'@") Nothing (Just "'Dot' only"), makeAttr "Color" ["color"] "ENC" (Cust "ColorList") Nothing (Just "[toWColor Black]") (Just "@['WC' ('X11Color' 'Black') Nothing]@") Nothing Nothing, makeAttr "ColorScheme" ["colorscheme"] "ENCG" (Cust "ColorScheme") Nothing (Just "X11") (Just "@'X11'@") Nothing Nothing, makeAttr "Comment" ["comment"] "ENG" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,- makeAttr "Compound" ["compound"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only"),+ makeAttr "Compound" ["compound"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "'Dot' only"), makeAttr "Concentrate" ["concentrate"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,- makeAttr "Constraint" ["constraint"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "dot only"),+ makeAttr "Constraint" ["constraint"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "'Dot' only"), makeAttr "Decorate" ["decorate"] "E" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,- makeAttr "DefaultDist" ["defaultdist"] "G" (Dbl) Nothing Nothing (Just "@1+(avg. len)*sqrt(abs(V))@ (unable to statically define)") (Just "The value of 'Epsilon'.") (Just "neato only, only if @'Pack' 'DontPack'@"),- makeAttr "Dim" ["dim"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "maximum of @10@; sfdp, fdp, neato only"),- makeAttr "Dimen" ["dimen"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "maximum of @10@; sfdp, fdp, neato only"),+ makeAttr "DefaultDist" ["defaultdist"] "G" (Dbl) Nothing Nothing (Just "@1+(avg. len)*sqrt(abs(V))@ (unable to statically define)") (Just "The value of 'Epsilon'.") (Just "'Neato' only, only if @'Pack' 'DontPack'@"),+ makeAttr "Dim" ["dim"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "maximum of @10@; 'Sfdp', 'Fdp', 'Neato' only"),+ makeAttr "Dimen" ["dimen"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "maximum of @10@; 'Sfdp', 'Fdp', 'Neato' only"), makeAttr "Dir" ["dir"] "E" (Cust "DirType") Nothing Nothing (Just "@'Forward'@ (directed), @'NoDir'@ (undirected)") Nothing Nothing,- makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "NoConstraints") (Just "@'NoConstraints'@") Nothing (Just "neato only"),+ makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "NoConstraints") (Just "@'NoConstraints'@") Nothing (Just "'Neato' only"), makeAttr "Distortion" ["distortion"] "N" (Dbl) Nothing (Just "0.0") (Just "@0.0@") (Just "@-100.0@") Nothing, makeAttr "DPI" ["dpi", "resolution"] "G" (Dbl) Nothing (Just "96.0") (Just "@96.0@, @0.0@") Nothing (Just "svg, bitmap output only; \\\"resolution\\\" is a synonym"), makeAttr "EdgeURL" ["edgeURL", "edgehref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"), makeAttr "EdgeTarget" ["edgetarget"] "E" (EStrng) Nothing Nothing (Just "none") Nothing (Just "svg, map only"), makeAttr "EdgeTooltip" ["edgetooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),- makeAttr "Epsilon" ["epsilon"] "G" (Dbl) Nothing Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "neato only"),- makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "(DVal 3)") (Just "@'DVal' 3@") Nothing (Just "not dot"),+ makeAttr "Epsilon" ["epsilon"] "G" (Dbl) Nothing Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "'Neato' only"),+ makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "(DVal 3)") (Just "@'DVal' 3@") Nothing (Just "not 'Dot'"), makeAttr "FillColor" ["fillcolor"] "NEC" (Cust "ColorList") Nothing (Just "[toWColor Black]") (Just "@['WC' ('X11Color' 'LightGray') Nothing]@ (nodes), @['WC' ('X11Color' 'Black') Nothing]@ (clusters)") Nothing Nothing,- makeAttr "FixedSize" ["fixedsize"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "FixedSize" ["fixedsize"] "N" (Cust "NodeSize") (Just "SetNodeSize") (Just "GrowAsNeeded") (Just "@'GrowAsNeeded'@") Nothing Nothing, makeAttr "FontColor" ["fontcolor"] "ENGC" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing, makeAttr "FontName" ["fontname"] "ENGC" (Strng) Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing, makeAttr "FontNames" ["fontnames"] "G" (Cust "SVGFontNames") Nothing (Just "SvgNames") (Just "@'SvgNames'@") Nothing (Just "svg only"),@@ -507,7 +507,7 @@ makeAttr "FontSize" ["fontsize"] "ENGC" (Dbl) Nothing (Just "14.0") (Just "@14.0@") (Just "@1.0@") Nothing, makeAttr "ForceLabels" ["forcelabels"] "G" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "only for 'XLabel' attributes, requires Graphviz >= 2.29.0"), makeAttr "GradientAngle" ["gradientangle"] "NCG" (Integ) Nothing (Just "0") (Just "0") Nothing (Just "requires Graphviz >= 2.29.0"),- makeAttr "Group" ["group"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "Group" ["group"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "'Dot' only"), makeAttr "HeadURL" ["headURL", "headhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"), makeAttr "Head_LP" ["head_lp"] "E" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.30.0"), makeAttr "HeadClip" ["headclip"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing,@@ -520,9 +520,10 @@ makeAttr "Image" ["image"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing, makeAttr "ImagePath" ["imagepath"] "G" (Cust "Paths") Nothing (Just "(Paths [])") (Just "@'Paths' []@") Nothing (Just "Printing and parsing is OS-specific, requires Graphviz >= 2.29.0"), makeAttr "ImageScale" ["imagescale"] "N" (Cust "ScaleType") (Just "UniformScale") (Just "NoScale") (Just "@'NoScale'@") Nothing Nothing,+ makeAttr "InputScale" ["inputscale"] "N" (Dbl) Nothing Nothing (Just "none") Nothing (Just "'Fdp', 'Neato' only, a value of @0@ is equivalent to being @72@, requires Graphviz >= 2.36.0"), makeAttr "Label" ["label"] "ENGC" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)") Nothing Nothing, makeAttr "LabelURL" ["labelURL", "labelhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),- makeAttr "LabelScheme" ["label_scheme"] "G" (Cust "LabelScheme") Nothing (Just "NotEdgeLabel") (Just "@'NotEdgeLabel'@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0"),+ makeAttr "LabelScheme" ["label_scheme"] "G" (Cust "LabelScheme") Nothing (Just "NotEdgeLabel") (Just "@'NotEdgeLabel'@") Nothing (Just "'Sfdp' only, requires Graphviz >= 2.28.0"), makeAttr "LabelAngle" ["labelangle"] "E" (Dbl) Nothing (Just "(-25.0)") (Just "@-25.0@") (Just "@-180.0@") Nothing, makeAttr "LabelDistance" ["labeldistance"] "E" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") Nothing, makeAttr "LabelFloat" ["labelfloat"] "E" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,@@ -534,80 +535,81 @@ makeAttr "LabelTarget" ["labeltarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"), makeAttr "LabelTooltip" ["labeltooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"), makeAttr "Landscape" ["landscape"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,- makeAttr "Layer" ["layer"] "EN" (Cust "LayerRange") Nothing (Just "[]") (Just "@[]@") Nothing Nothing,+ makeAttr "Layer" ["layer"] "ENC" (Cust "LayerRange") Nothing (Just "[]") (Just "@[]@") Nothing Nothing, makeAttr "LayerListSep" ["layerlistsep"] "G" (Cust "LayerListSep") Nothing (Just "(LLSep \",\")") (Just "@'LLSep' \\\",\\\"@") Nothing (Just "requires Graphviz >= 2.30.0"), makeAttr "Layers" ["layers"] "G" (Cust "LayerList") Nothing (Just "(LL [])") (Just "@'LL' []@") Nothing Nothing, makeAttr "LayerSelect" ["layerselect"] "G" (Cust "LayerRange") Nothing (Just "[]") (Just "@[]@") Nothing Nothing, makeAttr "LayerSep" ["layersep"] "G" (Cust "LayerSep") Nothing (Just "(LSep \" :\\t\")") (Just "@'LSep' \\\" :\\t\\\"@") Nothing Nothing, makeAttr "Layout" ["layout"] "G" (Cust "GraphvizCommand") Nothing Nothing Nothing Nothing Nothing,- makeAttr "Len" ["len"] "E" (Dbl) Nothing Nothing (Just "@1.0@ (neato), @0.3@ (fdp)") Nothing (Just "fdp, neato only"),- makeAttr "Levels" ["levels"] "G" (Integ) Nothing (Just "maxBound") (Just "@'maxBound'@") (Just "@0@") (Just "sfdp only"),- makeAttr "LevelsGap" ["levelsgap"] "G" (Dbl) Nothing (Just "0.0") (Just "@0.0@") Nothing (Just "neato only"),- makeAttr "LHead" ["lhead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "Len" ["len"] "E" (Dbl) Nothing Nothing (Just "@1.0@ ('Neato'), @0.3@ ('Fdp')") Nothing (Just "'Fdp', 'Neato' only"),+ makeAttr "Levels" ["levels"] "G" (Integ) Nothing (Just "maxBound") (Just "@'maxBound'@") (Just "@0@") (Just "'Sfdp' only"),+ makeAttr "LevelsGap" ["levelsgap"] "G" (Dbl) Nothing (Just "0.0") (Just "@0.0@") Nothing (Just "'Neato' only"),+ makeAttr "LHead" ["lhead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "'Dot' only"), makeAttr "LHeight" ["LHeight"] "GC" (Dbl) Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0"), makeAttr "LPos" ["lp"] "EGC" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only"),- makeAttr "LTail" ["ltail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "LTail" ["ltail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "'Dot' only"), makeAttr "LWidth" ["lwidth"] "GC" (Dbl) Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0"),- makeAttr "Margin" ["margin"] "NG" (Cust "DPoint") Nothing Nothing (Just "device dependent") Nothing Nothing,- makeAttr "MaxIter" ["maxiter"] "G" (Integ) Nothing Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp)") Nothing (Just "fdp, neato only"),- makeAttr "MCLimit" ["mclimit"] "G" (Dbl) Nothing (Just "1.0") (Just "@1.0@") Nothing (Just "dot only"),- makeAttr "MinDist" ["mindist"] "G" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") (Just "circo only"),- makeAttr "MinLen" ["minlen"] "E" (Integ) Nothing (Just "1") (Just "@1@") (Just "@0@") (Just "dot only"),- makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "Major") (Just "@'Major'@") Nothing (Just "neato only"),- makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "ShortPath") (Just "@'ShortPath'@") Nothing (Just "neato only"),- makeAttr "Mosek" ["mosek"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "neato only; requires the Mosek software"),- makeAttr "NodeSep" ["nodesep"] "G" (Dbl) Nothing (Just "0.25") (Just "@0.25@") (Just "@0.02@") (Just "dot only"),+ makeAttr "Margin" ["margin"] "NGC" (Cust "DPoint") Nothing Nothing (Just "device dependent") Nothing Nothing,+ makeAttr "MaxIter" ["maxiter"] "G" (Integ) Nothing Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ ('Fdp')") Nothing (Just "'Fdp', 'Neato' only"),+ makeAttr "MCLimit" ["mclimit"] "G" (Dbl) Nothing (Just "1.0") (Just "@1.0@") Nothing (Just "'Dot' only"),+ makeAttr "MinDist" ["mindist"] "G" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") (Just "'Circo' only"),+ makeAttr "MinLen" ["minlen"] "E" (Integ) Nothing (Just "1") (Just "@1@") (Just "@0@") (Just "'Dot' only"),+ makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "Major") (Just "@'Major'@ (actually @'Spring'@ for 'Sfdp', but this isn't used as a default in this library)") Nothing (Just "'Neato', 'Sfdp' only"),+ makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "ShortPath") (Just "@'ShortPath'@") Nothing (Just "'Neato' only"),+ makeAttr "Mosek" ["mosek"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "'Neato' only; requires the Mosek software"),+ makeAttr "NodeSep" ["nodesep"] "G" (Dbl) Nothing (Just "0.25") (Just "@0.25@") (Just "@0.02@") Nothing, makeAttr "NoJustify" ["nojustify"] "GCNE" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,- makeAttr "Normalize" ["normalize"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "not dot"),- makeAttr "Nslimit" ["nslimit"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "dot only"),- makeAttr "Nslimit1" ["nslimit1"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "dot only"),- makeAttr "Ordering" ["ordering"] "GN" (Cust "Order") Nothing Nothing (Just "none") Nothing (Just "dot only"),+ makeAttr "Normalize" ["normalize"] "G" (Cust "Normalized") (Just "IsNormalized") (Just "NotNormalized") (Just "@'NotNormalized'@") Nothing (Just "not 'Dot'"),+ makeAttr "Nslimit" ["nslimit"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "'Dot' only"),+ makeAttr "Nslimit1" ["nslimit1"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "'Dot' only"),+ makeAttr "Ordering" ["ordering"] "GN" (Cust "Order") Nothing Nothing (Just "none") Nothing (Just "'Dot' only"), makeAttr "Orientation" ["orientation"] "N" (Dbl) Nothing (Just "0.0") (Just "@0.0@") (Just "@360.0@") Nothing, makeAttr "OutputOrder" ["outputorder"] "G" (Cust "OutputMode") Nothing (Just "BreadthFirst") (Just "@'BreadthFirst'@") Nothing Nothing,- makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not dot"),- makeAttr "OverlapScaling" ["overlap_scaling"] "G" (Dbl) Nothing (Just "(-4)") (Just "@-4@") (Just "@-1.0e10@") (Just "prism only"),- makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "DontPack") (Just "@'DontPack'@") Nothing (Just "not dot"),- makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "PackNode") (Just "@'PackNode'@") Nothing (Just "not dot"),+ makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not 'Dot'"),+ makeAttr "OverlapScaling" ["overlap_scaling"] "G" (Dbl) Nothing (Just "(-4)") (Just "@-4@") (Just "@-1.0e10@") (Just "'PrismOverlap' only"),+ makeAttr "OverlapShrink" ["overlap_shrink"] "G" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "'PrismOverlap' only, requires Graphviz >= 2.36.0"),+ makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "DontPack") (Just "@'DontPack'@") Nothing Nothing,+ makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "PackNode") (Just "@'PackNode'@") Nothing Nothing, makeAttr "Pad" ["pad"] "G" (Cust "DPoint") Nothing (Just "(DVal 0.0555)") (Just "@'DVal' 0.0555@ (4 points)") Nothing Nothing, makeAttr "Page" ["page"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing, makeAttr "PageDir" ["pagedir"] "G" (Cust "PageDir") Nothing (Just "Bl") (Just "@'Bl'@") Nothing Nothing, makeAttr "PenColor" ["pencolor"] "C" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing, makeAttr "PenWidth" ["penwidth"] "CNE" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") Nothing, makeAttr "Peripheries" ["peripheries"] "NC" (Integ) Nothing (Just "1") (Just "shape default (nodes), @1@ (clusters)") (Just "0") Nothing,- makeAttr "Pin" ["pin"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "fdp, neato only"),+ makeAttr "Pin" ["pin"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "'Fdp', 'Neato' only"), makeAttr "Pos" ["pos"] "EN" (Cust "Pos") Nothing Nothing Nothing Nothing Nothing,- makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "sfdp only"),+ makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "'Sfdp' only"), makeAttr "Quantum" ["quantum"] "G" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@0.0@") Nothing,- makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing Nothing (Just "dot only"),- makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "FromTop") (Just "@'FromTop'@") Nothing (Just "dot only"),- makeAttr "RankSep" ["ranksep"] "G" (Cust "[Double]") Nothing Nothing (Just "@[0.5]@ (dot), @[1.0]@ (twopi)") (Just "[0.02]") (Just "twopi, dot only"),+ makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing Nothing (Just "'Dot' only"),+ makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "FromTop") (Just "@'FromTop'@") Nothing (Just "'Dot' only"),+ makeAttr "RankSep" ["ranksep"] "G" (Cust "[Double]") Nothing Nothing (Just "@[0.5]@ ('Dot'), @[1.0]@ ('Twopi')") (Just "@[0.02]@") (Just "'Twopi', 'Dot' only"), makeAttr "Ratio" ["ratio"] "G" (Cust "Ratios") Nothing Nothing Nothing Nothing Nothing, makeAttr "Rects" ["rects"] "N" (Cust "[Rect]") Nothing Nothing Nothing Nothing (Just "write only"), makeAttr "Regular" ["regular"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,- makeAttr "ReMinCross" ["remincross"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only"),- makeAttr "RepulsiveForce" ["repulsiveforce"] "G" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") (Just "sfdp only"),- makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "(NodeName \"\")") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "circo, twopi only"),+ makeAttr "ReMinCross" ["remincross"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "'Dot' only"),+ makeAttr "RepulsiveForce" ["repulsiveforce"] "G" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0.0@") (Just "'Sfdp' only"),+ makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "(NodeName \"\")") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "'Circo', 'Twopi' only"), makeAttr "Rotate" ["rotate"] "G" (Integ) Nothing (Just "0") (Just "@0@") Nothing Nothing,- makeAttr "Rotation" ["rotation"] "G" (Dbl) Nothing (Just "0") (Just "@0@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0"),- makeAttr "SameHead" ["samehead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),- makeAttr "SameTail" ["sametail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "Rotation" ["rotation"] "G" (Dbl) Nothing (Just "0") (Just "@0@") Nothing (Just "'Sfdp' only, requires Graphviz >= 2.28.0"),+ makeAttr "SameHead" ["samehead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "'Dot' only"),+ makeAttr "SameTail" ["sametail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "'Dot' only"), makeAttr "SamplePoints" ["samplepoints"] "N" (Integ) Nothing Nothing (Just "@8@ (output), @20@ (overlap and image maps)") Nothing Nothing,- makeAttr "Scale" ["scale"] "G" (Cust "DPoint") Nothing Nothing Nothing Nothing (Just "twopi only, requires Graphviz >= 2.28.0"),- makeAttr "SearchSize" ["searchsize"] "G" (Integ) Nothing (Just "30") (Just "@30@") Nothing (Just "dot only"),- makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "(DVal 4)") (Just "@'DVal' 4@") Nothing (Just "not dot"),+ makeAttr "Scale" ["scale"] "G" (Cust "DPoint") Nothing Nothing Nothing Nothing (Just "Not 'Dot', requires Graphviz >= 2.28.0 (>= 2.38.0 for anything except 'TwoPi')"),+ makeAttr "SearchSize" ["searchsize"] "G" (Integ) Nothing (Just "30") (Just "@30@") Nothing (Just "'Dot' only"),+ makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "(DVal 4)") (Just "@'DVal' 4@") Nothing (Just "not 'Dot'"), makeAttr "Shape" ["shape"] "N" (Cust "Shape") Nothing (Just "Ellipse") (Just "@'Ellipse'@") Nothing Nothing,- makeAttr "ShowBoxes" ["showboxes"] "ENG" (Integ) Nothing (Just "0") (Just "@0@") (Just "@0@") (Just "dot only; used for debugging by printing PostScript guide boxes"),+ makeAttr "ShowBoxes" ["showboxes"] "ENG" (Integ) Nothing (Just "0") (Just "@0@") (Just "@0@") (Just "'Dot' only; used for debugging by printing PostScript guide boxes"), makeAttr "Sides" ["sides"] "N" (Integ) Nothing (Just "4") (Just "@4@") (Just "@0@") Nothing, makeAttr "Size" ["size"] "G" (Cust "GraphSize") Nothing Nothing Nothing Nothing Nothing, makeAttr "Skew" ["skew"] "N" (Dbl) Nothing (Just "0.0") (Just "@0.0@") (Just "@-100.0@") Nothing,- makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "NoSmooth") (Just "@'NoSmooth'@") Nothing (Just "sfdp only"),+ makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "NoSmooth") (Just "@'NoSmooth'@") Nothing (Just "'Sfdp' only"), makeAttr "SortV" ["sortv"] "GCN" (Cust "Word16") Nothing (Just "0") (Just "@0@") (Just "@0@") Nothing,- makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") Nothing (Just "@'SplineEdges'@ (dot), @'LineEdges'@ (other)") Nothing Nothing,- makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing Nothing (Just "@'StartStyleSeed' 'RandomStyle' seed@ for some unknown fixed seed.") Nothing (Just "fdp, neato only"),- makeAttr "Style" ["style"] "ENC" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") Nothing (Just "@'SplineEdges'@ ('Dot'), @'LineEdges'@ (other)") Nothing Nothing,+ makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing Nothing (Just "@'StartStyleSeed' 'RandomStyle' seed@ for some unknown fixed seed.") Nothing (Just "'Fdp', 'Neato' only"),+ makeAttr "Style" ["style"] "ENCG" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing Nothing, makeAttr "StyleSheet" ["stylesheet"] "G" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only"), makeAttr "TailURL" ["tailURL", "tailhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),- makeAttr "Tail_LP" ["tail_lp"] "E" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only"),+ makeAttr "Tail_LP" ["tail_lp"] "E" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.30.0"), makeAttr "TailClip" ["tailclip"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing, makeAttr "TailLabel" ["taillabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing, makeAttr "TailPort" ["tailport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing,@@ -618,9 +620,10 @@ makeAttr "TrueColor" ["truecolor"] "G" (Bl) (Just "True") Nothing Nothing Nothing (Just "bitmap output only"), makeAttr "Vertices" ["vertices"] "N" (Cust "[Point]") Nothing Nothing Nothing Nothing (Just "write only"), makeAttr "ViewPort" ["viewport"] "G" (Cust "ViewPort") Nothing Nothing (Just "none") Nothing Nothing,- makeAttr "VoroMargin" ["voro_margin"] "G" (Dbl) Nothing (Just "0.05") (Just "@0.05@") (Just "@0.0@") (Just "not dot"),- makeAttr "Weight" ["weight"] "E" (Dbl) Nothing (Just "1.0") (Just "@1.0@") (Just "@0@ (dot), @1@ (neato,fdp,sfdp)") Nothing,+ makeAttr "VoroMargin" ["voro_margin"] "G" (Dbl) Nothing (Just "0.05") (Just "@0.05@") (Just "@0.0@") (Just "not 'Dot'"),+ makeAttr "Weight" ["weight"] "E" (Cust "Number") Nothing (Just "(Int 1)") (Just "@'Int' 1@") (Just "@'Int' 0@ ('Dot'), @'Int' 1@ ('Neato','Fdp','Sfdp')") (Just "as of Graphviz 2.30: weights for dot need to be 'Int's"), makeAttr "Width" ["width"] "N" (Dbl) Nothing (Just "0.75") (Just "@0.75@") (Just "@0.01@") Nothing,+ makeAttr "XDotVersion" ["xdotversion"] "G" (Cust "Version") Nothing Nothing Nothing Nothing (Just "xdot only, requires Graphviz >= 2.34.0, equivalent to specifying version of xdot to be used"), makeAttr "XLabel" ["xlabel"] "EN" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing (Just "requires Graphviz >= 2.29.0"), makeAttr "XLP" ["xlp"] "EN" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.29.0") -- END RECEIVE ORGTBL Attributes@@ -649,165 +652,171 @@ valid Haskell value (add parens if needed) with the exception that double-quotes should be escaped. +* @C-c `@ can be used to edit a field that has been narrowed.+ #+ORGTBL: SEND Attributes orgtbl-to-generic :skip 2 :splice t :hline nil :no-escape t :lstart " makeAttr " :lend "," :llend "" :sep " " :fmt (1 cell-quote 2 cell-to-list 3 cell-quote 4 cell-parens 5 cell-to-maybe 6 cell-to-maybe 7 cell-to-maybe 8 cell-to-maybe 9 cell-to-maybe)-| Constructor | Allowed names | Used By | Type | Parsing default | Default value | Default for Documentation | Minimum | Comment notes |-|--------------------+--------------------+---------+--------------------------+-----------------+----------------------------+-----------------------------------------------------------------------------------------------------+---------------------------------+------------------------------------------------------------------|-| Damping | Damping | G | Dbl | | 0.99 | @0.99@ | @0.0@ | neato only |-| K | K | GC | Dbl | | 0.3 | @0.3@ | @0@ | sfdp, fdp only |-| URL | URL href | ENGC | EStrng | | \"\" | none | | svg, postscript, map only |-| Area | area | NC | Dbl | | 1.0 | @1.0@ | @>0@ | patchwork only, requires Graphviz >= 2.30.0 |-| ArrowHead | arrowhead | E | Cust "ArrowType" | | normal | @'normal'@ | | |-| ArrowSize | arrowsize | E | Dbl | | 1.0 | @1.0@ | @0.0@ | |-| ArrowTail | arrowtail | E | Cust "ArrowType" | | normal | @'normal'@ | | |-| Aspect | aspect | G | Cust "AspectType" | | | | | dot only |-| BoundingBox | bb | G | Cust "Rect" | | | | | write only |-| BgColor | bgcolor | GC | Cust "ColorList" | | [] | @[]@ | | |-| Center | center | G | Bl | True | False | @'False'@ | | |-| ClusterRank | clusterrank | G | Cust "ClusterMode" | | Local | @'Local'@ | | dot only |-| Color | color | ENC | Cust "ColorList" | | [toWColor Black] | @['WC' ('X11Color' 'Black') Nothing]@ | | |-| ColorScheme | colorscheme | ENCG | Cust "ColorScheme" | | X11 | @'X11'@ | | |-| Comment | comment | ENG | Strng | | \"\" | @\\\"\\\"@ | | |-| Compound | compound | G | Bl | True | False | @'False'@ | | dot only |-| Concentrate | concentrate | G | Bl | True | False | @'False'@ | | |-| Constraint | constraint | E | Bl | True | True | @'True'@ | | dot only |-| Decorate | decorate | E | Bl | True | False | @'False'@ | | |-| DefaultDist | defaultdist | G | Dbl | | | @1+(avg. len)*sqrt(abs(V))@ (unable to statically define) | The value of 'Epsilon'. | neato only, only if @'Pack' 'DontPack'@ |-| Dim | dim | G | Integ | | 2 | @2@ | @2@ | maximum of @10@; sfdp, fdp, neato only |-| Dimen | dimen | G | Integ | | 2 | @2@ | @2@ | maximum of @10@; sfdp, fdp, neato only |-| Dir | dir | E | Cust "DirType" | | | @'Forward'@ (directed), @'NoDir'@ (undirected) | | |-| DirEdgeConstraints | diredgeconstraints | G | Cust "DEConstraints" | EdgeConstraints | NoConstraints | @'NoConstraints'@ | | neato only |-| Distortion | distortion | N | Dbl | | 0.0 | @0.0@ | @-100.0@ | |-| DPI | dpi resolution | G | Dbl | | 96.0 | @96.0@, @0.0@ | | svg, bitmap output only; \\\"resolution\\\" is a synonym |-| EdgeURL | edgeURL edgehref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |-| EdgeTarget | edgetarget | E | EStrng | | | none | | svg, map only |-| EdgeTooltip | edgetooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |-| Epsilon | epsilon | G | Dbl | | | @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@) | | neato only |-| ESep | esep | G | Cust "DPoint" | | (DVal 3) | @'DVal' 3@ | | not dot |-| FillColor | fillcolor | NEC | Cust "ColorList" | | [toWColor Black] | @['WC' ('X11Color' 'LightGray') Nothing]@ (nodes), @['WC' ('X11Color' 'Black') Nothing]@ (clusters) | | |-| FixedSize | fixedsize | N | Bl | True | False | @'False'@ | | |-| FontColor | fontcolor | ENGC | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |-| FontName | fontname | ENGC | Strng | | \"Times-Roman\" | @\\\"Times-Roman\\\"@ | | |-| FontNames | fontnames | G | Cust "SVGFontNames" | | SvgNames | @'SvgNames'@ | | svg only |-| FontPath | fontpath | G | Cust "Paths" | | | system dependent | | |-| FontSize | fontsize | ENGC | Dbl | | 14.0 | @14.0@ | @1.0@ | |-| ForceLabels | forcelabels | G | Bl | True | True | @'True'@ | | only for 'XLabel' attributes, requires Graphviz >= 2.29.0 |-| GradientAngle | gradientangle | NCG | Integ | | 0 | 0 | | requires Graphviz >= 2.29.0 |-| Group | group | N | Strng | | \"\" | @\\\"\\\"@ | | dot only |-| HeadURL | headURL headhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |-| Head_LP | head_lp | E | Cust "Point" | | | | | write only, requires Graphviz >= 2.30.0 |-| HeadClip | headclip | E | Bl | True | True | @'True'@ | | |-| HeadLabel | headlabel | E | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | |-| HeadPort | headport | E | Cust "PortPos" | | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@ | | |-| HeadTarget | headtarget | E | EStrng | | \"\" | none | | svg, map only |-| HeadTooltip | headtooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |-| Height | height | N | Dbl | | 0.5 | @0.5@ | @0.02@ | |-| ID | id | GNE | EStrng | | \"\" | @\\\"\\\"@ | | svg, postscript, map only |-| Image | image | N | Strng | | \"\" | @\\\"\\\"@ | | |-| ImagePath | imagepath | G | Cust "Paths" | | (Paths []) | @'Paths' []@ | | Printing and parsing is OS-specific, requires Graphviz >= 2.29.0 |-| ImageScale | imagescale | N | Cust "ScaleType" | UniformScale | NoScale | @'NoScale'@ | | |-| Label | label | ENGC | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise) | | |-| LabelURL | labelURL labelhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |-| LabelScheme | label_scheme | G | Cust "LabelScheme" | | NotEdgeLabel | @'NotEdgeLabel'@ | | sfdp only, requires Graphviz >= 2.28.0 |-| LabelAngle | labelangle | E | Dbl | | (-25.0) | @-25.0@ | @-180.0@ | |-| LabelDistance | labeldistance | E | Dbl | | 1.0 | @1.0@ | @0.0@ | |-| LabelFloat | labelfloat | E | Bl | True | False | @'False'@ | | |-| LabelFontColor | labelfontcolor | E | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |-| LabelFontName | labelfontname | E | Strng | | \"Times-Roman\" | @\\\"Times-Roman\\\"@ | | |-| LabelFontSize | labelfontsize | E | Dbl | | 14.0 | @14.0@ | @1.0@ | |-| LabelJust | labeljust | GC | Cust "Justification" | | JCenter | @'JCenter'@ | | |-| LabelLoc | labelloc | GCN | Cust "VerticalPlacement" | | VTop | @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes) | | |-| LabelTarget | labeltarget | E | EStrng | | \"\" | none | | svg, map only |-| LabelTooltip | labeltooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |-| Landscape | landscape | G | Bl | True | False | @'False'@ | | |-| Layer | layer | EN | Cust "LayerRange" | | [] | @[]@ | | |-| LayerListSep | layerlistsep | G | Cust "LayerListSep" | | (LLSep \",\") | @'LLSep' \\\",\\\"@ | | requires Graphviz >= 2.30.0 |-| Layers | layers | G | Cust "LayerList" | | (LL []) | @'LL' []@ | | |-| LayerSelect | layerselect | G | Cust "LayerRange" | | [] | @[]@ | | |-| LayerSep | layersep | G | Cust "LayerSep" | | (LSep \" :\\t\") | @'LSep' \\\" :\\t\\\"@ | | |-| Layout | layout | G | Cust "GraphvizCommand" | | | | | |-| Len | len | E | Dbl | | | @1.0@ (neato), @0.3@ (fdp) | | fdp, neato only |-| Levels | levels | G | Integ | | maxBound | @'maxBound'@ | @0@ | sfdp only |-| LevelsGap | levelsgap | G | Dbl | | 0.0 | @0.0@ | | neato only |-| LHead | lhead | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |-| LHeight | LHeight | GC | Dbl | | | | | write only, requires Graphviz >= 2.28.0 |-| LPos | lp | EGC | Cust "Point" | | | | | write only |-| LTail | ltail | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |-| LWidth | lwidth | GC | Dbl | | | | | write only, requires Graphviz >= 2.28.0 |-| Margin | margin | NG | Cust "DPoint" | | | device dependent | | |-| MaxIter | maxiter | G | Integ | | | @100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp) | | fdp, neato only |-| MCLimit | mclimit | G | Dbl | | 1.0 | @1.0@ | | dot only |-| MinDist | mindist | G | Dbl | | 1.0 | @1.0@ | @0.0@ | circo only |-| MinLen | minlen | E | Integ | | 1 | @1@ | @0@ | dot only |-| Mode | mode | G | Cust "ModeType" | | Major | @'Major'@ | | neato only |-| Model | model | G | Cust "Model" | | ShortPath | @'ShortPath'@ | | neato only |-| Mosek | mosek | G | Bl | True | False | @'False'@ | | neato only; requires the Mosek software |-| NodeSep | nodesep | G | Dbl | | 0.25 | @0.25@ | @0.02@ | dot only |-| NoJustify | nojustify | GCNE | Bl | True | False | @'False'@ | | |-| Normalize | normalize | G | Bl | True | False | @'False'@ | | not dot |-| Nslimit | nslimit | G | Dbl | | | | | dot only |-| Nslimit1 | nslimit1 | G | Dbl | | | | | dot only |-| Ordering | ordering | GN | Cust "Order" | | | none | | dot only |-| Orientation | orientation | N | Dbl | | 0.0 | @0.0@ | @360.0@ | |-| OutputOrder | outputorder | G | Cust "OutputMode" | | BreadthFirst | @'BreadthFirst'@ | | |-| Overlap | overlap | G | Cust "Overlap" | KeepOverlaps | KeepOverlaps | @'KeepOverlaps'@ | | not dot |-| OverlapScaling | overlap_scaling | G | Dbl | | (-4) | @-4@ | @-1.0e10@ | prism only |-| Pack | pack | G | Cust "Pack" | DoPack | DontPack | @'DontPack'@ | | not dot |-| PackMode | packmode | G | Cust "PackMode" | | PackNode | @'PackNode'@ | | not dot |-| Pad | pad | G | Cust "DPoint" | | (DVal 0.0555) | @'DVal' 0.0555@ (4 points) | | |-| Page | page | G | Cust "Point" | | | | | |-| PageDir | pagedir | G | Cust "PageDir" | | Bl | @'Bl'@ | | |-| PenColor | pencolor | C | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |-| PenWidth | penwidth | CNE | Dbl | | 1.0 | @1.0@ | @0.0@ | |-| Peripheries | peripheries | NC | Integ | | 1 | shape default (nodes), @1@ (clusters) | 0 | |-| Pin | pin | N | Bl | True | False | @'False'@ | | fdp, neato only |-| Pos | pos | EN | Cust "Pos" | | | | | |-| QuadTree | quadtree | G | Cust "QuadType" | NormalQT | NormalQT | @'NormalQT'@ | | sfdp only |-| Quantum | quantum | G | Dbl | | 0 | @0.0@ | @0.0@ | |-| Rank | rank | S | Cust "RankType" | | | | | dot only |-| RankDir | rankdir | G | Cust "RankDir" | | FromTop | @'FromTop'@ | | dot only |-| RankSep | ranksep | G | Cust "[Double]" | | | @[0.5]@ (dot), @[1.0]@ (twopi) | [0.02] | twopi, dot only |-| Ratio | ratio | G | Cust "Ratios" | | | | | |-| Rects | rects | N | Cust "[Rect]" | | | | | write only |-| Regular | regular | N | Bl | True | False | @'False'@ | | |-| ReMinCross | remincross | G | Bl | True | False | @'False'@ | | dot only |-| RepulsiveForce | repulsiveforce | G | Dbl | | 1.0 | @1.0@ | @0.0@ | sfdp only |-| Root | root | GN | Cust "Root" | IsCentral | (NodeName \"\") | @'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes) | | circo, twopi only |-| Rotate | rotate | G | Integ | | 0 | @0@ | | |-| Rotation | rotation | G | Dbl | | 0 | @0@ | | sfdp only, requires Graphviz >= 2.28.0 |-| SameHead | samehead | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |-| SameTail | sametail | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |-| SamplePoints | samplepoints | N | Integ | | | @8@ (output), @20@ (overlap and image maps) | | |-| Scale | scale | G | Cust "DPoint" | | | | | twopi only, requires Graphviz >= 2.28.0 |-| SearchSize | searchsize | G | Integ | | 30 | @30@ | | dot only |-| Sep | sep | G | Cust "DPoint" | | (DVal 4) | @'DVal' 4@ | | not dot |-| Shape | shape | N | Cust "Shape" | | Ellipse | @'Ellipse'@ | | |-| ShowBoxes | showboxes | ENG | Integ | | 0 | @0@ | @0@ | dot only; used for debugging by printing PostScript guide boxes |-| Sides | sides | N | Integ | | 4 | @4@ | @0@ | |-| Size | size | G | Cust "GraphSize" | | | | | |-| Skew | skew | N | Dbl | | 0.0 | @0.0@ | @-100.0@ | |-| Smoothing | smoothing | G | Cust "SmoothType" | | NoSmooth | @'NoSmooth'@ | | sfdp only |-| SortV | sortv | GCN | Cust "Word16" | | 0 | @0@ | @0@ | |-| Splines | splines | G | Cust "EdgeType" | SplineEdges | | @'SplineEdges'@ (dot), @'LineEdges'@ (other) | | |-| Start | start | G | Cust "StartType" | | | @'StartStyleSeed' 'RandomStyle' seed@ for some unknown fixed seed. | | fdp, neato only |-| Style | style | ENC | Cust "[StyleItem]" | | | | | |-| StyleSheet | stylesheet | G | Strng | | \"\" | @\\\"\\\"@ | | svg only |-| TailURL | tailURL tailhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |-| Tail_LP | tail_lp | E | Cust "Point" | | | | | write only |-| TailClip | tailclip | E | Bl | True | True | @'True'@ | | |-| TailLabel | taillabel | E | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | |-| TailPort | tailport | E | Cust "PortPos" | | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@ | | |-| TailTarget | tailtarget | E | EStrng | | \"\" | none | | svg, map only |-| TailTooltip | tailtooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |-| Target | target | ENGC | EStrng | | \"\" | none | | svg, map only |-| Tooltip | tooltip | NEC | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |-| TrueColor | truecolor | G | Bl | True | | | | bitmap output only |-| Vertices | vertices | N | Cust "[Point]" | | | | | write only |-| ViewPort | viewport | G | Cust "ViewPort" | | | none | | |-| VoroMargin | voro_margin | G | Dbl | | 0.05 | @0.05@ | @0.0@ | not dot |-| Weight | weight | E | Dbl | | 1.0 | @1.0@ | @0@ (dot), @1@ (neato,fdp,sfdp) | |-| Width | width | N | Dbl | | 0.75 | @0.75@ | @0.01@ | |-| XLabel | xlabel | EN | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | requires Graphviz >= 2.29.0 |-| XLP | xlp | EN | Cust "Point" | | | | | write only, requires Graphviz >= 2.29.0 |+| Constructor | Allowed names | Used By | Type | Parse def | Default value | Default for Documentation | Minimum | Comment notes |+|-----------------+-----------------+---------+-----------------+------------+-----------------+----------------------+------------+----------------------|+| <15> | <15> | | <15> | <10> | <15> | <20> | <10> | <20> |+| Damping | Damping | G | Dbl | | 0.99 | @0.99@ | @0.0@ | 'Neato' only |+| K | K | GC | Dbl | | 0.3 | @0.3@ | @0@ | 'Sfdp', 'Fdp' only |+| URL | URL href | ENGC | EStrng | | \"\" | none | | svg, postscript, map only |+| Area | area | NC | Dbl | | 1.0 | @1.0@ | @>0@ | 'Patchwork' only, requires Graphviz >= 2.30.0 |+| ArrowHead | arrowhead | E | Cust "ArrowType" | | normal | @'normal'@ | | |+| ArrowSize | arrowsize | E | Dbl | | 1.0 | @1.0@ | @0.0@ | |+| ArrowTail | arrowtail | E | Cust "ArrowType" | | normal | @'normal'@ | | |+| Background | _background | G | Strng | | \"\" | none | | xdot only |+| BoundingBox | bb | G | Cust "Rect" | | | | | write only |+| BgColor | bgcolor | GC | Cust "ColorList" | | [] | @[]@ | | |+| Center | center | G | Bl | True | False | @'False'@ | | |+| ClusterRank | clusterrank | G | Cust "ClusterMode" | | Local | @'Local'@ | | 'Dot' only |+| Color | color | ENC | Cust "ColorList" | | [toWColor Black] | @['WC' ('X11Color' 'Black') Nothing]@ | | |+| ColorScheme | colorscheme | ENCG | Cust "ColorScheme" | | X11 | @'X11'@ | | |+| Comment | comment | ENG | Strng | | \"\" | @\\\"\\\"@ | | |+| Compound | compound | G | Bl | True | False | @'False'@ | | 'Dot' only |+| Concentrate | concentrate | G | Bl | True | False | @'False'@ | | |+| Constraint | constraint | E | Bl | True | True | @'True'@ | | 'Dot' only |+| Decorate | decorate | E | Bl | True | False | @'False'@ | | |+| DefaultDist | defaultdist | G | Dbl | | | @1+(avg. len)*sqrt(abs(V))@ (unable to statically define) | The value of 'Epsilon'. | 'Neato' only, only if @'Pack' 'DontPack'@ |+| Dim | dim | G | Integ | | 2 | @2@ | @2@ | maximum of @10@; 'Sfdp', 'Fdp', 'Neato' only |+| Dimen | dimen | G | Integ | | 2 | @2@ | @2@ | maximum of @10@; 'Sfdp', 'Fdp', 'Neato' only |+| Dir | dir | E | Cust "DirType" | | | @'Forward'@ (directed), @'NoDir'@ (undirected) | | |+| DirEdgeConstraints | diredgeconstraints | G | Cust "DEConstraints" | EdgeConstraints | NoConstraints | @'NoConstraints'@ | | 'Neato' only |+| Distortion | distortion | N | Dbl | | 0.0 | @0.0@ | @-100.0@ | |+| DPI | dpi resolution | G | Dbl | | 96.0 | @96.0@, @0.0@ | | svg, bitmap output only; \\\"resolution\\\" is a synonym |+| EdgeURL | edgeURL edgehref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| EdgeTarget | edgetarget | E | EStrng | | | none | | svg, map only |+| EdgeTooltip | edgetooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Epsilon | epsilon | G | Dbl | | | @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@) | | 'Neato' only |+| ESep | esep | G | Cust "DPoint" | | (DVal 3) | @'DVal' 3@ | | not 'Dot' |+| FillColor | fillcolor | NEC | Cust "ColorList" | | [toWColor Black] | @['WC' ('X11Color' 'LightGray') Nothing]@ (nodes), @['WC' ('X11Color' 'Black') Nothing]@ (clusters) | | |+| FixedSize | fixedsize | N | Cust "NodeSize" | SetNodeSize | GrowAsNeeded | @'GrowAsNeeded'@ | | |+| FontColor | fontcolor | ENGC | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |+| FontName | fontname | ENGC | Strng | | \"Times-Roman\" | @\\\"Times-Roman\\\"@ | | |+| FontNames | fontnames | G | Cust "SVGFontNames" | | SvgNames | @'SvgNames'@ | | svg only |+| FontPath | fontpath | G | Cust "Paths" | | | system dependent | | |+| FontSize | fontsize | ENGC | Dbl | | 14.0 | @14.0@ | @1.0@ | |+| ForceLabels | forcelabels | G | Bl | True | True | @'True'@ | | only for 'XLabel' attributes, requires Graphviz >= 2.29.0 |+| GradientAngle | gradientangle | NCG | Integ | | 0 | 0 | | requires Graphviz >= 2.29.0 |+| Group | group | N | Strng | | \"\" | @\\\"\\\"@ | | 'Dot' only |+| HeadURL | headURL headhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| Head_LP | head_lp | E | Cust "Point" | | | | | write only, requires Graphviz >= 2.30.0 |+| HeadClip | headclip | E | Bl | True | True | @'True'@ | | |+| HeadLabel | headlabel | E | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | |+| HeadPort | headport | E | Cust "PortPos" | | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@ | | |+| HeadTarget | headtarget | E | EStrng | | \"\" | none | | svg, map only |+| HeadTooltip | headtooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Height | height | N | Dbl | | 0.5 | @0.5@ | @0.02@ | |+| ID | id | GNE | EStrng | | \"\" | @\\\"\\\"@ | | svg, postscript, map only |+| Image | image | N | Strng | | \"\" | @\\\"\\\"@ | | |+| ImagePath | imagepath | G | Cust "Paths" | | (Paths []) | @'Paths' []@ | | Printing and parsing is OS-specific, requires Graphviz >= 2.29.0 |+| ImageScale | imagescale | N | Cust "ScaleType" | UniformScale | NoScale | @'NoScale'@ | | |+| InputScale | inputscale | N | Dbl | | | none | | 'Fdp', 'Neato' only, a value of @0@ is equivalent to being @72@, requires Graphviz >= 2.36.0 |+| Label | label | ENGC | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise) | | |+| LabelURL | labelURL labelhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| LabelScheme | label_scheme | G | Cust "LabelScheme" | | NotEdgeLabel | @'NotEdgeLabel'@ | | 'Sfdp' only, requires Graphviz >= 2.28.0 |+| LabelAngle | labelangle | E | Dbl | | (-25.0) | @-25.0@ | @-180.0@ | |+| LabelDistance | labeldistance | E | Dbl | | 1.0 | @1.0@ | @0.0@ | |+| LabelFloat | labelfloat | E | Bl | True | False | @'False'@ | | |+| LabelFontColor | labelfontcolor | E | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |+| LabelFontName | labelfontname | E | Strng | | \"Times-Roman\" | @\\\"Times-Roman\\\"@ | | |+| LabelFontSize | labelfontsize | E | Dbl | | 14.0 | @14.0@ | @1.0@ | |+| LabelJust | labeljust | GC | Cust "Justification" | | JCenter | @'JCenter'@ | | |+| LabelLoc | labelloc | GCN | Cust "VerticalPlacement" | | VTop | @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes) | | |+| LabelTarget | labeltarget | E | EStrng | | \"\" | none | | svg, map only |+| LabelTooltip | labeltooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Landscape | landscape | G | Bl | True | False | @'False'@ | | |+| Layer | layer | ENC | Cust "LayerRange" | | [] | @[]@ | | |+| LayerListSep | layerlistsep | G | Cust "LayerListSep" | | (LLSep \",\") | @'LLSep' \\\",\\\"@ | | requires Graphviz >= 2.30.0 |+| Layers | layers | G | Cust "LayerList" | | (LL []) | @'LL' []@ | | |+| LayerSelect | layerselect | G | Cust "LayerRange" | | [] | @[]@ | | |+| LayerSep | layersep | G | Cust "LayerSep" | | (LSep \" :\\t\") | @'LSep' \\\" :\\t\\\"@ | | |+| Layout | layout | G | Cust "GraphvizCommand" | | | | | |+| Len | len | E | Dbl | | | @1.0@ ('Neato'), @0.3@ ('Fdp') | | 'Fdp', 'Neato' only |+| Levels | levels | G | Integ | | maxBound | @'maxBound'@ | @0@ | 'Sfdp' only |+| LevelsGap | levelsgap | G | Dbl | | 0.0 | @0.0@ | | 'Neato' only |+| LHead | lhead | E | Strng | | \"\" | @\\\"\\\"@ | | 'Dot' only |+| LHeight | LHeight | GC | Dbl | | | | | write only, requires Graphviz >= 2.28.0 |+| LPos | lp | EGC | Cust "Point" | | | | | write only |+| LTail | ltail | E | Strng | | \"\" | @\\\"\\\"@ | | 'Dot' only |+| LWidth | lwidth | GC | Dbl | | | | | write only, requires Graphviz >= 2.28.0 |+| Margin | margin | NGC | Cust "DPoint" | | | device dependent | | |+| MaxIter | maxiter | G | Integ | | | @100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ ('Fdp') | | 'Fdp', 'Neato' only |+| MCLimit | mclimit | G | Dbl | | 1.0 | @1.0@ | | 'Dot' only |+| MinDist | mindist | G | Dbl | | 1.0 | @1.0@ | @0.0@ | 'Circo' only |+| MinLen | minlen | E | Integ | | 1 | @1@ | @0@ | 'Dot' only |+| Mode | mode | G | Cust "ModeType" | | Major | @'Major'@ (actually @'Spring'@ for 'Sfdp', but this isn't used as a default in this library) | | 'Neato', 'Sfdp' only |+| Model | model | G | Cust "Model" | | ShortPath | @'ShortPath'@ | | 'Neato' only |+| Mosek | mosek | G | Bl | True | False | @'False'@ | | 'Neato' only; requires the Mosek software |+| NodeSep | nodesep | G | Dbl | | 0.25 | @0.25@ | @0.02@ | |+| NoJustify | nojustify | GCNE | Bl | True | False | @'False'@ | | |+| Normalize | normalize | G | Cust "Normalized" | IsNormalized | NotNormalized | @'NotNormalized'@ | | not 'Dot' |+| Nslimit | nslimit | G | Dbl | | | | | 'Dot' only |+| Nslimit1 | nslimit1 | G | Dbl | | | | | 'Dot' only |+| Ordering | ordering | GN | Cust "Order" | | | none | | 'Dot' only |+| Orientation | orientation | N | Dbl | | 0.0 | @0.0@ | @360.0@ | |+| OutputOrder | outputorder | G | Cust "OutputMode" | | BreadthFirst | @'BreadthFirst'@ | | |+| Overlap | overlap | G | Cust "Overlap" | KeepOverlaps | KeepOverlaps | @'KeepOverlaps'@ | | not 'Dot' |+| OverlapScaling | overlap_scaling | G | Dbl | | (-4) | @-4@ | @-1.0e10@ | 'PrismOverlap' only |+| OverlapShrink | overlap_shrink | G | Bl | True | True | @'True'@ | | 'PrismOverlap' only, requires Graphviz >= 2.36.0 |+| Pack | pack | G | Cust "Pack" | DoPack | DontPack | @'DontPack'@ | | |+| PackMode | packmode | G | Cust "PackMode" | | PackNode | @'PackNode'@ | | |+| Pad | pad | G | Cust "DPoint" | | (DVal 0.0555) | @'DVal' 0.0555@ (4 points) | | |+| Page | page | G | Cust "Point" | | | | | |+| PageDir | pagedir | G | Cust "PageDir" | | Bl | @'Bl'@ | | |+| PenColor | pencolor | C | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |+| PenWidth | penwidth | CNE | Dbl | | 1.0 | @1.0@ | @0.0@ | |+| Peripheries | peripheries | NC | Integ | | 1 | shape default (nodes), @1@ (clusters) | 0 | |+| Pin | pin | N | Bl | True | False | @'False'@ | | 'Fdp', 'Neato' only |+| Pos | pos | EN | Cust "Pos" | | | | | |+| QuadTree | quadtree | G | Cust "QuadType" | NormalQT | NormalQT | @'NormalQT'@ | | 'Sfdp' only |+| Quantum | quantum | G | Dbl | | 0 | @0.0@ | @0.0@ | |+| Rank | rank | S | Cust "RankType" | | | | | 'Dot' only |+| RankDir | rankdir | G | Cust "RankDir" | | FromTop | @'FromTop'@ | | 'Dot' only |+| RankSep | ranksep | G | Cust "[Double]" | | | @[0.5]@ ('Dot'), @[1.0]@ ('Twopi') | @[0.02]@ | 'Twopi', 'Dot' only |+| Ratio | ratio | G | Cust "Ratios" | | | | | |+| Rects | rects | N | Cust "[Rect]" | | | | | write only |+| Regular | regular | N | Bl | True | False | @'False'@ | | |+| ReMinCross | remincross | G | Bl | True | False | @'False'@ | | 'Dot' only |+| RepulsiveForce | repulsiveforce | G | Dbl | | 1.0 | @1.0@ | @0.0@ | 'Sfdp' only |+| Root | root | GN | Cust "Root" | IsCentral | (NodeName \"\") | @'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes) | | 'Circo', 'Twopi' only |+| Rotate | rotate | G | Integ | | 0 | @0@ | | |+| Rotation | rotation | G | Dbl | | 0 | @0@ | | 'Sfdp' only, requires Graphviz >= 2.28.0 |+| SameHead | samehead | E | Strng | | \"\" | @\\\"\\\"@ | | 'Dot' only |+| SameTail | sametail | E | Strng | | \"\" | @\\\"\\\"@ | | 'Dot' only |+| SamplePoints | samplepoints | N | Integ | | | @8@ (output), @20@ (overlap and image maps) | | |+| Scale | scale | G | Cust "DPoint" | | | | | Not 'Dot', requires Graphviz >= 2.28.0 (>= 2.38.0 for anything except 'TwoPi') |+| SearchSize | searchsize | G | Integ | | 30 | @30@ | | 'Dot' only |+| Sep | sep | G | Cust "DPoint" | | (DVal 4) | @'DVal' 4@ | | not 'Dot' |+| Shape | shape | N | Cust "Shape" | | Ellipse | @'Ellipse'@ | | |+| ShowBoxes | showboxes | ENG | Integ | | 0 | @0@ | @0@ | 'Dot' only; used for debugging by printing PostScript guide boxes |+| Sides | sides | N | Integ | | 4 | @4@ | @0@ | |+| Size | size | G | Cust "GraphSize" | | | | | |+| Skew | skew | N | Dbl | | 0.0 | @0.0@ | @-100.0@ | |+| Smoothing | smoothing | G | Cust "SmoothType" | | NoSmooth | @'NoSmooth'@ | | 'Sfdp' only |+| SortV | sortv | GCN | Cust "Word16" | | 0 | @0@ | @0@ | |+| Splines | splines | G | Cust "EdgeType" | SplineEdges | | @'SplineEdges'@ ('Dot'), @'LineEdges'@ (other) | | |+| Start | start | G | Cust "StartType" | | | @'StartStyleSeed' 'RandomStyle' seed@ for some unknown fixed seed. | | 'Fdp', 'Neato' only |+| Style | style | ENCG | Cust "[StyleItem]" | | | | | |+| StyleSheet | stylesheet | G | Strng | | \"\" | @\\\"\\\"@ | | svg only |+| TailURL | tailURL tailhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| Tail_LP | tail_lp | E | Cust "Point" | | | | | write only, requires Graphviz >= 2.30.0 |+| TailClip | tailclip | E | Bl | True | True | @'True'@ | | |+| TailLabel | taillabel | E | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | |+| TailPort | tailport | E | Cust "PortPos" | | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@ | | |+| TailTarget | tailtarget | E | EStrng | | \"\" | none | | svg, map only |+| TailTooltip | tailtooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Target | target | ENGC | EStrng | | \"\" | none | | svg, map only |+| Tooltip | tooltip | NEC | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| TrueColor | truecolor | G | Bl | True | | | | bitmap output only |+| Vertices | vertices | N | Cust "[Point]" | | | | | write only |+| ViewPort | viewport | G | Cust "ViewPort" | | | none | | |+| VoroMargin | voro_margin | G | Dbl | | 0.05 | @0.05@ | @0.0@ | not 'Dot' |+| Weight | weight | E | Cust "Number" | | (Int 1) | @'Int' 1@ | @'Int' 0@ ('Dot'), @'Int' 1@ ('Neato','Fdp','Sfdp') | as of Graphviz 2.30: weights for dot need to be 'Int's |+| Width | width | N | Dbl | | 0.75 | @0.75@ | @0.01@ | |+| XDotVersion | xdotversion | G | Cust "Version" | | | | | xdot only, requires Graphviz >= 2.34.0, equivalent to specifying version of xdot to be used |+| XLabel | xlabel | EN | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | requires Graphviz >= 2.29.0 |+| XLP | xlp | EN | Cust "Point" | | | | | write only, requires Graphviz >= 2.29.0 | -}
utils/TestParsing.hs view
@@ -1,4 +1,4 @@-#!/usr/bin/runhaskell+{-# LANGUAGE MultiParamTypeClasses #-} {- | Module : TestParsing@@ -14,21 +14,21 @@ -} module Main where -import Data.GraphViz+import Data.GraphViz+import Data.GraphViz.Commands.IO (hGetStrict, toUTF8)+import Data.GraphViz.Exception+import Data.GraphViz.Parsing (runParser)+import Data.GraphViz.PreProcessing (preProcess) import qualified Data.GraphViz.Types.Generalised as G-import Data.GraphViz.Parsing(runParser)-import Data.GraphViz.PreProcessing(preProcess)-import Data.GraphViz.Commands.IO(hGetStrict, toUTF8)-import Data.GraphViz.Exception -import qualified Data.Text.Lazy as T-import Data.Text.Lazy(Text)+import Control.Exception (SomeException, evaluate, try)+import Control.Monad (filterM, liftM) import qualified Data.ByteString.Lazy as B-import Control.Exception(try, evaluate, SomeException)-import Control.Monad(liftM, filterM)-import System.Directory-import System.FilePath-import System.Environment(getArgs)+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import System.Directory+import System.Environment (getArgs)+import System.FilePath -- ----------------------------------------------------------------------------- @@ -41,7 +41,7 @@ \\n\ \One way of using this file:\n\t\ \$ locate -r \".*\\.\\(gv\\|dot\\)$\" -0\- \ | xargs -0 runhaskell TestParsing.hs"+ \ | xargs -0 TestParsing.hs" tryParsing [fp] = do isDir <- doesDirectoryExist fp if isDir then mapM_ tryParseFile =<< getDContents fp