graphviz 2009.5.1 → 2999.0.0.0
raw patch · 8 files changed
+2242/−893 lines, 8 filesdep +extensible-exceptionsdep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: extensible-exceptions
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.GraphViz.Attributes: BL :: PageDir
- Data.GraphViz.Attributes: BR :: PageDir
- Data.GraphViz.Attributes: Dot :: ArrowType
- Data.GraphViz.Attributes: Dpi :: Double -> Attribute
- Data.GraphViz.Attributes: FitX :: ScaleType
- Data.GraphViz.Attributes: FitY :: ScaleType
- Data.GraphViz.Attributes: LB :: PageDir
- Data.GraphViz.Attributes: LT :: PageDir
- Data.GraphViz.Attributes: Minlen :: Double -> Attribute
- Data.GraphViz.Attributes: Nodesep :: Double -> Attribute
- Data.GraphViz.Attributes: None :: DirType
- Data.GraphViz.Attributes: PointList :: [Point] -> PointList
- Data.GraphViz.Attributes: RB :: PageDir
- Data.GraphViz.Attributes: RT :: PageDir
- Data.GraphViz.Attributes: RankSep :: Double -> Attribute
- Data.GraphViz.Attributes: Scale :: ScaleType
- Data.GraphViz.Attributes: TL :: PageDir
- Data.GraphViz.Attributes: TR :: PageDir
- Data.GraphViz.Attributes: Unknown :: String -> String -> Attribute
- Data.GraphViz.Attributes: data ColorType
- Data.GraphViz.Attributes: data ShapeType
- Data.GraphViz.Attributes: data StyleType
- Data.GraphViz.Attributes: instance Eq ColorType
- Data.GraphViz.Attributes: instance Eq PointList
- Data.GraphViz.Attributes: instance Eq ShapeType
- Data.GraphViz.Attributes: instance Eq StyleType
- Data.GraphViz.Attributes: instance Show ColorType
- Data.GraphViz.Attributes: instance Show PointList
- Data.GraphViz.Attributes: instance Show ShapeType
- Data.GraphViz.Attributes: instance Show StyleType
- Data.GraphViz.Attributes: newtype PointList
- Data.GraphViz.Attributes: readArrowType :: Parser Char ArrowType
- Data.GraphViz.Attributes: readAttribute :: Parser Char Attribute
- Data.GraphViz.Attributes: readAttributesList :: Parser Char [Attribute]
- Data.GraphViz.Attributes: readBool :: Parser Char Bool
- Data.GraphViz.Attributes: readColorType :: Parser Char ColorType
- Data.GraphViz.Attributes: readDirType :: Parser Char DirType
- Data.GraphViz.Attributes: readJustification :: Parser Char Justification
- Data.GraphViz.Attributes: readOutputMode :: Parser Char OutputMode
- Data.GraphViz.Attributes: readPageDir :: Parser Char PageDir
- Data.GraphViz.Attributes: readPoint :: Parser Char Point
- Data.GraphViz.Attributes: readPointList :: Parser Char PointList
- Data.GraphViz.Attributes: readRect :: Parser Char Rect
- Data.GraphViz.Attributes: readScaleType :: Parser Char ScaleType
- Data.GraphViz.Attributes: readShapeType :: Parser Char ShapeType
- Data.GraphViz.Attributes: readString :: Parser Char String
- Data.GraphViz.Attributes: readStyleType :: Parser Char StyleType
- Data.GraphViz.Attributes: readVerticalPlacement :: Parser Char VerticalPlacement
- Data.GraphViz.Commands: DotCmd :: GraphvizCommand
- Data.GraphViz.Types: readDotGraph :: Parser Char DotGraph
+ Data.GraphViz.Attributes: AllLayers :: LayerID
+ Data.GraphViz.Attributes: Aspect :: AspectType -> Attribute
+ Data.GraphViz.Attributes: AspectRatio :: Double -> Ratios
+ Data.GraphViz.Attributes: AutoRatio :: Ratios
+ Data.GraphViz.Attributes: AvgDist :: SmoothType
+ Data.GraphViz.Attributes: Bl :: PageDir
+ Data.GraphViz.Attributes: Br :: PageDir
+ Data.GraphViz.Attributes: CenterPoint :: CompassPoint
+ Data.GraphViz.Attributes: Charset :: String -> Attribute
+ Data.GraphViz.Attributes: ClusterRank :: ClusterMode -> Attribute
+ Data.GraphViz.Attributes: ColorName :: String -> Color
+ Data.GraphViz.Attributes: ColorScheme :: String -> Attribute
+ Data.GraphViz.Attributes: Comment :: String -> Attribute
+ Data.GraphViz.Attributes: Compound :: Bool -> Attribute
+ Data.GraphViz.Attributes: CompressRatio :: Ratios
+ Data.GraphViz.Attributes: DPI :: Double -> Attribute
+ Data.GraphViz.Attributes: Damping :: Double -> Attribute
+ Data.GraphViz.Attributes: Dim :: Int -> Attribute
+ Data.GraphViz.Attributes: Dimen :: Int -> Attribute
+ Data.GraphViz.Attributes: DirEdgeConstraints :: (Either String Bool) -> Attribute
+ Data.GraphViz.Attributes: Distortion :: Double -> Attribute
+ Data.GraphViz.Attributes: DotArrow :: ArrowType
+ Data.GraphViz.Attributes: ESep :: (Either Double Point) -> Attribute
+ Data.GraphViz.Attributes: East :: CompassPoint
+ Data.GraphViz.Attributes: EdgeHref :: URL -> Attribute
+ Data.GraphViz.Attributes: EdgeTarget :: String -> Attribute
+ Data.GraphViz.Attributes: EdgeTooltip :: String -> Attribute
+ Data.GraphViz.Attributes: EdgeURL :: URL -> Attribute
+ Data.GraphViz.Attributes: Epsilon :: Double -> Attribute
+ Data.GraphViz.Attributes: ExpandRatio :: Ratios
+ Data.GraphViz.Attributes: FastQT :: QuadType
+ Data.GraphViz.Attributes: FillBoth :: ScaleType
+ Data.GraphViz.Attributes: FillHeight :: ScaleType
+ Data.GraphViz.Attributes: FillRatio :: Ratios
+ Data.GraphViz.Attributes: FillWidth :: ScaleType
+ Data.GraphViz.Attributes: FontNames :: String -> Attribute
+ Data.GraphViz.Attributes: FontPath :: String -> Attribute
+ Data.GraphViz.Attributes: FromBottom :: RankDir
+ Data.GraphViz.Attributes: FromLeft :: RankDir
+ Data.GraphViz.Attributes: FromRight :: RankDir
+ Data.GraphViz.Attributes: FromTop :: RankDir
+ Data.GraphViz.Attributes: Global :: ClusterMode
+ Data.GraphViz.Attributes: GraphDist :: SmoothType
+ Data.GraphViz.Attributes: HSV :: Int -> Int -> Int -> Color
+ Data.GraphViz.Attributes: HeadHref :: URL -> Attribute
+ Data.GraphViz.Attributes: HeadPort :: PortPos -> Attribute
+ Data.GraphViz.Attributes: HeadTarget :: QuotedString -> Attribute
+ Data.GraphViz.Attributes: HeadTooltip :: QuotedString -> Attribute
+ Data.GraphViz.Attributes: HeadURL :: URL -> Attribute
+ Data.GraphViz.Attributes: Href :: URL -> Attribute
+ Data.GraphViz.Attributes: ID :: (Either String URL) -> Attribute
+ Data.GraphViz.Attributes: K :: Double -> Attribute
+ Data.GraphViz.Attributes: LHead :: String -> Attribute
+ Data.GraphViz.Attributes: LL :: String -> [(String, String)] -> LayerList
+ Data.GraphViz.Attributes: LP :: Point -> Attribute
+ Data.GraphViz.Attributes: LRID :: LayerID -> LayerRange
+ Data.GraphViz.Attributes: LRInt :: Int -> LayerID
+ Data.GraphViz.Attributes: LRName :: String -> LayerID
+ Data.GraphViz.Attributes: LRS :: LayerID -> String -> LayerID -> LayerRange
+ Data.GraphViz.Attributes: LTail :: String -> Attribute
+ Data.GraphViz.Attributes: LabelHref :: URL -> Attribute
+ Data.GraphViz.Attributes: LabelTarget :: String -> Attribute
+ Data.GraphViz.Attributes: LabelTooltip :: String -> Attribute
+ Data.GraphViz.Attributes: LabelURL :: URL -> Attribute
+ Data.GraphViz.Attributes: Layer :: LayerRange -> Attribute
+ Data.GraphViz.Attributes: LayerSep :: String -> Attribute
+ Data.GraphViz.Attributes: Layers :: LayerList -> Attribute
+ Data.GraphViz.Attributes: Layout :: String -> Attribute
+ Data.GraphViz.Attributes: Lb :: PageDir
+ Data.GraphViz.Attributes: Levels :: Int -> Attribute
+ Data.GraphViz.Attributes: LevelsGap :: Double -> Attribute
+ Data.GraphViz.Attributes: Local :: ClusterMode
+ Data.GraphViz.Attributes: Lt :: PageDir
+ Data.GraphViz.Attributes: MCLimit :: Double -> Attribute
+ Data.GraphViz.Attributes: MaxIter :: Int -> Attribute
+ Data.GraphViz.Attributes: MaxRank :: RankType
+ Data.GraphViz.Attributes: MinLen :: Int -> Attribute
+ Data.GraphViz.Attributes: MinRank :: RankType
+ Data.GraphViz.Attributes: Mode :: String -> Attribute
+ Data.GraphViz.Attributes: Model :: String -> Attribute
+ Data.GraphViz.Attributes: Mosek :: Bool -> Attribute
+ Data.GraphViz.Attributes: NoCP :: CompassPoint
+ Data.GraphViz.Attributes: NoCluster :: ClusterMode
+ Data.GraphViz.Attributes: NoDir :: DirType
+ Data.GraphViz.Attributes: NoQT :: QuadType
+ Data.GraphViz.Attributes: NoSmooth :: SmoothType
+ Data.GraphViz.Attributes: NodeName :: String -> FocusType
+ Data.GraphViz.Attributes: NodeSep :: Double -> Attribute
+ Data.GraphViz.Attributes: NormalQT :: QuadType
+ Data.GraphViz.Attributes: North :: CompassPoint
+ Data.GraphViz.Attributes: NorthEast :: CompassPoint
+ Data.GraphViz.Attributes: NorthWest :: CompassPoint
+ Data.GraphViz.Attributes: Nslimit :: Double -> Attribute
+ Data.GraphViz.Attributes: Nslimit1 :: Double -> Attribute
+ Data.GraphViz.Attributes: Ordering :: String -> Attribute
+ Data.GraphViz.Attributes: OrientationGraph :: String -> Attribute
+ Data.GraphViz.Attributes: OverlapScaling :: Double -> Attribute
+ Data.GraphViz.Attributes: PP :: CompassPoint -> PortPos
+ Data.GraphViz.Attributes: Pack :: (Either Bool Int) -> Attribute
+ Data.GraphViz.Attributes: PackArray :: Bool -> Bool -> (Maybe Int) -> PackMode
+ Data.GraphViz.Attributes: PackClust :: PackMode
+ Data.GraphViz.Attributes: PackGraph :: PackMode
+ Data.GraphViz.Attributes: PackMode :: PackMode -> Attribute
+ Data.GraphViz.Attributes: PackNode :: PackMode
+ Data.GraphViz.Attributes: PenWidth :: Double -> Attribute
+ Data.GraphViz.Attributes: Peripheries :: Int -> Attribute
+ Data.GraphViz.Attributes: Pin :: Bool -> Attribute
+ Data.GraphViz.Attributes: PowerDist :: SmoothType
+ Data.GraphViz.Attributes: QS :: String -> QuotedString
+ Data.GraphViz.Attributes: QuadTree :: (Either QuadType Bool) -> Attribute
+ Data.GraphViz.Attributes: RNG :: SmoothType
+ Data.GraphViz.Attributes: Random :: STStyle
+ Data.GraphViz.Attributes: Rank :: RankType -> Attribute
+ Data.GraphViz.Attributes: Ranksep :: Double -> Attribute
+ Data.GraphViz.Attributes: RatioOnly :: Double -> AspectType
+ Data.GraphViz.Attributes: RatioPassCount :: Double -> Int -> AspectType
+ Data.GraphViz.Attributes: Rb :: PageDir
+ Data.GraphViz.Attributes: ReMinCross :: Bool -> Attribute
+ Data.GraphViz.Attributes: Rects :: Rect -> Attribute
+ Data.GraphViz.Attributes: RegularStyle :: STStyle
+ Data.GraphViz.Attributes: RepulsiveForce :: Double -> Attribute
+ Data.GraphViz.Attributes: Resolution :: Double -> Attribute
+ Data.GraphViz.Attributes: Root :: (Either String Bool) -> Attribute
+ Data.GraphViz.Attributes: Rt :: PageDir
+ Data.GraphViz.Attributes: ST :: (Maybe STStyle) -> (Maybe Int) -> StartType
+ Data.GraphViz.Attributes: SameRank :: RankType
+ Data.GraphViz.Attributes: SamplePoints :: Int -> Attribute
+ Data.GraphViz.Attributes: SearchSize :: Int -> Attribute
+ Data.GraphViz.Attributes: Self :: STStyle
+ Data.GraphViz.Attributes: ShapeFile :: String -> Attribute
+ Data.GraphViz.Attributes: ShowBoxes :: Int -> Attribute
+ Data.GraphViz.Attributes: SinkRank :: RankType
+ Data.GraphViz.Attributes: Smoothing :: SmoothType -> Attribute
+ Data.GraphViz.Attributes: SortV :: Int -> Attribute
+ Data.GraphViz.Attributes: SourceRank :: RankType
+ Data.GraphViz.Attributes: South :: CompassPoint
+ Data.GraphViz.Attributes: SouthEast :: CompassPoint
+ Data.GraphViz.Attributes: SouthWest :: CompassPoint
+ Data.GraphViz.Attributes: Spline :: (Maybe Point) -> (Maybe Point) -> [Point] -> Spline
+ Data.GraphViz.Attributes: Spring :: SmoothType
+ Data.GraphViz.Attributes: Start :: StartType -> Attribute
+ Data.GraphViz.Attributes: Stl :: StyleName -> (Maybe String) -> Style
+ Data.GraphViz.Attributes: StyleSheet :: String -> Attribute
+ Data.GraphViz.Attributes: TailHref :: URL -> Attribute
+ Data.GraphViz.Attributes: TailPort :: PortPos -> Attribute
+ Data.GraphViz.Attributes: TailTarget :: String -> Attribute
+ Data.GraphViz.Attributes: TailTooltip :: String -> Attribute
+ Data.GraphViz.Attributes: TailURL :: URL -> Attribute
+ Data.GraphViz.Attributes: Target :: String -> Attribute
+ Data.GraphViz.Attributes: Tl :: PageDir
+ Data.GraphViz.Attributes: Tooltip :: String -> Attribute
+ Data.GraphViz.Attributes: Tr :: PageDir
+ Data.GraphViz.Attributes: TriangleSmooth :: SmoothType
+ Data.GraphViz.Attributes: TrueColor :: Bool -> Attribute
+ Data.GraphViz.Attributes: URL :: URL -> Attribute
+ Data.GraphViz.Attributes: UStr :: String -> URL
+ Data.GraphViz.Attributes: UniformScale :: ScaleType
+ Data.GraphViz.Attributes: VP :: Double -> Double -> Double -> Maybe FocusType -> ViewPort
+ Data.GraphViz.Attributes: Vertices :: [Point] -> Attribute
+ Data.GraphViz.Attributes: ViewPort :: ViewPort -> Attribute
+ Data.GraphViz.Attributes: VoroMargin :: Double -> Attribute
+ Data.GraphViz.Attributes: West :: CompassPoint
+ Data.GraphViz.Attributes: XY :: Point -> FocusType
+ Data.GraphViz.Attributes: Z :: Double -> Attribute
+ Data.GraphViz.Attributes: data AspectType
+ Data.GraphViz.Attributes: data ClusterMode
+ Data.GraphViz.Attributes: data Color
+ Data.GraphViz.Attributes: data CompassPoint
+ Data.GraphViz.Attributes: data FocusType
+ Data.GraphViz.Attributes: data LayerID
+ Data.GraphViz.Attributes: data LayerList
+ Data.GraphViz.Attributes: data LayerRange
+ Data.GraphViz.Attributes: data PackMode
+ Data.GraphViz.Attributes: data QuadType
+ Data.GraphViz.Attributes: data RankDir
+ Data.GraphViz.Attributes: data RankType
+ Data.GraphViz.Attributes: data Ratios
+ Data.GraphViz.Attributes: data STStyle
+ Data.GraphViz.Attributes: data Shape
+ Data.GraphViz.Attributes: data SmoothType
+ Data.GraphViz.Attributes: data Spline
+ Data.GraphViz.Attributes: data StartType
+ Data.GraphViz.Attributes: data Style
+ Data.GraphViz.Attributes: data StyleName
+ Data.GraphViz.Attributes: data ViewPort
+ Data.GraphViz.Attributes: defLayerSep :: [Char]
+ Data.GraphViz.Attributes: focus :: ViewPort -> Maybe FocusType
+ Data.GraphViz.Attributes: hVal :: ViewPort -> Double
+ Data.GraphViz.Attributes: hue :: Color -> Int
+ Data.GraphViz.Attributes: instance Eq AspectType
+ Data.GraphViz.Attributes: instance Eq ClusterMode
+ Data.GraphViz.Attributes: instance Eq Color
+ Data.GraphViz.Attributes: instance Eq CompassPoint
+ Data.GraphViz.Attributes: instance Eq FocusType
+ Data.GraphViz.Attributes: instance Eq LayerID
+ Data.GraphViz.Attributes: instance Eq LayerList
+ Data.GraphViz.Attributes: instance Eq LayerRange
+ Data.GraphViz.Attributes: instance Eq PackMode
+ Data.GraphViz.Attributes: instance Eq PortPos
+ Data.GraphViz.Attributes: instance Eq QuadType
+ Data.GraphViz.Attributes: instance Eq QuotedString
+ Data.GraphViz.Attributes: instance Eq RankDir
+ Data.GraphViz.Attributes: instance Eq RankType
+ Data.GraphViz.Attributes: instance Eq Ratios
+ Data.GraphViz.Attributes: instance Eq STStyle
+ Data.GraphViz.Attributes: instance Eq Shape
+ Data.GraphViz.Attributes: instance Eq SmoothType
+ Data.GraphViz.Attributes: instance Eq Spline
+ Data.GraphViz.Attributes: instance Eq StartType
+ Data.GraphViz.Attributes: instance Eq Style
+ Data.GraphViz.Attributes: instance Eq StyleName
+ Data.GraphViz.Attributes: instance Eq URL
+ Data.GraphViz.Attributes: instance Eq ViewPort
+ Data.GraphViz.Attributes: instance Parseable ArrowType
+ Data.GraphViz.Attributes: instance Parseable AspectType
+ Data.GraphViz.Attributes: instance Parseable Attribute
+ Data.GraphViz.Attributes: instance Parseable ClusterMode
+ Data.GraphViz.Attributes: instance Parseable Color
+ Data.GraphViz.Attributes: instance Parseable CompassPoint
+ Data.GraphViz.Attributes: instance Parseable DirType
+ Data.GraphViz.Attributes: instance Parseable FocusType
+ Data.GraphViz.Attributes: instance Parseable Justification
+ Data.GraphViz.Attributes: instance Parseable LayerID
+ Data.GraphViz.Attributes: instance Parseable LayerList
+ Data.GraphViz.Attributes: instance Parseable LayerRange
+ Data.GraphViz.Attributes: instance Parseable OutputMode
+ Data.GraphViz.Attributes: instance Parseable PackMode
+ Data.GraphViz.Attributes: instance Parseable PageDir
+ Data.GraphViz.Attributes: instance Parseable Point
+ Data.GraphViz.Attributes: instance Parseable PortPos
+ Data.GraphViz.Attributes: instance Parseable QuadType
+ Data.GraphViz.Attributes: instance Parseable QuotedString
+ Data.GraphViz.Attributes: instance Parseable RankDir
+ Data.GraphViz.Attributes: instance Parseable RankType
+ Data.GraphViz.Attributes: instance Parseable Ratios
+ Data.GraphViz.Attributes: instance Parseable Rect
+ Data.GraphViz.Attributes: instance Parseable STStyle
+ Data.GraphViz.Attributes: instance Parseable ScaleType
+ Data.GraphViz.Attributes: instance Parseable Shape
+ Data.GraphViz.Attributes: instance Parseable SmoothType
+ Data.GraphViz.Attributes: instance Parseable Spline
+ Data.GraphViz.Attributes: instance Parseable StartType
+ Data.GraphViz.Attributes: instance Parseable Style
+ Data.GraphViz.Attributes: instance Parseable StyleName
+ Data.GraphViz.Attributes: instance Parseable URL
+ Data.GraphViz.Attributes: instance Parseable VerticalPlacement
+ Data.GraphViz.Attributes: instance Parseable ViewPort
+ Data.GraphViz.Attributes: instance Read ArrowType
+ Data.GraphViz.Attributes: instance Read AspectType
+ Data.GraphViz.Attributes: instance Read Attribute
+ Data.GraphViz.Attributes: instance Read ClusterMode
+ Data.GraphViz.Attributes: instance Read Color
+ Data.GraphViz.Attributes: instance Read CompassPoint
+ Data.GraphViz.Attributes: instance Read DirType
+ Data.GraphViz.Attributes: instance Read FocusType
+ Data.GraphViz.Attributes: instance Read Justification
+ Data.GraphViz.Attributes: instance Read LayerID
+ Data.GraphViz.Attributes: instance Read LayerList
+ Data.GraphViz.Attributes: instance Read LayerRange
+ Data.GraphViz.Attributes: instance Read OutputMode
+ Data.GraphViz.Attributes: instance Read PackMode
+ Data.GraphViz.Attributes: instance Read PageDir
+ Data.GraphViz.Attributes: instance Read Point
+ Data.GraphViz.Attributes: instance Read PortPos
+ Data.GraphViz.Attributes: instance Read QuadType
+ Data.GraphViz.Attributes: instance Read QuotedString
+ Data.GraphViz.Attributes: instance Read RankDir
+ Data.GraphViz.Attributes: instance Read RankType
+ Data.GraphViz.Attributes: instance Read Ratios
+ Data.GraphViz.Attributes: instance Read Rect
+ Data.GraphViz.Attributes: instance Read STStyle
+ Data.GraphViz.Attributes: instance Read ScaleType
+ Data.GraphViz.Attributes: instance Read Shape
+ Data.GraphViz.Attributes: instance Read SmoothType
+ Data.GraphViz.Attributes: instance Read Spline
+ Data.GraphViz.Attributes: instance Read StartType
+ Data.GraphViz.Attributes: instance Read Style
+ Data.GraphViz.Attributes: instance Read StyleName
+ Data.GraphViz.Attributes: instance Read URL
+ Data.GraphViz.Attributes: instance Read VerticalPlacement
+ Data.GraphViz.Attributes: instance Read ViewPort
+ Data.GraphViz.Attributes: instance Show AspectType
+ Data.GraphViz.Attributes: instance Show ClusterMode
+ Data.GraphViz.Attributes: instance Show Color
+ Data.GraphViz.Attributes: instance Show CompassPoint
+ Data.GraphViz.Attributes: instance Show FocusType
+ Data.GraphViz.Attributes: instance Show LayerID
+ Data.GraphViz.Attributes: instance Show LayerList
+ Data.GraphViz.Attributes: instance Show LayerRange
+ Data.GraphViz.Attributes: instance Show PackMode
+ Data.GraphViz.Attributes: instance Show PortPos
+ Data.GraphViz.Attributes: instance Show QuadType
+ Data.GraphViz.Attributes: instance Show QuotedString
+ Data.GraphViz.Attributes: instance Show RankDir
+ Data.GraphViz.Attributes: instance Show RankType
+ Data.GraphViz.Attributes: instance Show Ratios
+ Data.GraphViz.Attributes: instance Show STStyle
+ Data.GraphViz.Attributes: instance Show Shape
+ Data.GraphViz.Attributes: instance Show SmoothType
+ Data.GraphViz.Attributes: instance Show Spline
+ Data.GraphViz.Attributes: instance Show StartType
+ Data.GraphViz.Attributes: instance Show Style
+ Data.GraphViz.Attributes: instance Show StyleName
+ Data.GraphViz.Attributes: instance Show URL
+ Data.GraphViz.Attributes: instance Show ViewPort
+ Data.GraphViz.Attributes: newtype PortPos
+ Data.GraphViz.Attributes: newtype QuotedString
+ Data.GraphViz.Attributes: newtype URL
+ Data.GraphViz.Attributes: parseColor :: Parse Color
+ Data.GraphViz.Attributes: parseLayerName :: Parse String
+ Data.GraphViz.Attributes: parseLayerSep :: Parse String
+ Data.GraphViz.Attributes: parsePoint :: Parse Point
+ Data.GraphViz.Attributes: parseSpline :: Parse Spline
+ Data.GraphViz.Attributes: qStr :: QuotedString -> String
+ Data.GraphViz.Attributes: saturation :: Color -> Int
+ Data.GraphViz.Attributes: showColor :: Color -> String
+ Data.GraphViz.Attributes: showPoint :: Point -> String
+ Data.GraphViz.Attributes: showSpline :: Spline -> String
+ Data.GraphViz.Attributes: urlString :: URL -> String
+ Data.GraphViz.Attributes: usedByClusters :: Attribute -> Bool
+ Data.GraphViz.Attributes: usedByEdges :: Attribute -> Bool
+ Data.GraphViz.Attributes: usedByGraphs :: Attribute -> Bool
+ Data.GraphViz.Attributes: usedByNodes :: Attribute -> Bool
+ Data.GraphViz.Attributes: usedBySubGraphs :: Attribute -> Bool
+ Data.GraphViz.Attributes: value :: Color -> Int
+ Data.GraphViz.Attributes: wVal :: ViewPort -> Double
+ Data.GraphViz.Attributes: zVal :: ViewPort -> Double
+ Data.GraphViz.Commands: Dot :: GraphvizCommand
+ Data.GraphViz.ParserCombinators: char :: Char -> Parse Char
+ Data.GraphViz.ParserCombinators: class Parseable a
+ Data.GraphViz.ParserCombinators: commaSep :: (Parseable a, Parseable b) => Parse (a, b)
+ Data.GraphViz.ParserCombinators: commaSep' :: Parse a -> Parse b -> Parse (a, b)
+ Data.GraphViz.ParserCombinators: hasString :: String -> Parse Bool
+ Data.GraphViz.ParserCombinators: instance (Parseable a) => Parseable [a]
+ Data.GraphViz.ParserCombinators: instance (Parseable a, Parseable b) => Parseable (Either a b)
+ Data.GraphViz.ParserCombinators: instance Parseable Bool
+ Data.GraphViz.ParserCombinators: instance Parseable Char
+ Data.GraphViz.ParserCombinators: instance Parseable Double
+ Data.GraphViz.ParserCombinators: instance Parseable Int
+ Data.GraphViz.ParserCombinators: newline :: Parse String
+ Data.GraphViz.ParserCombinators: optionalQuoted :: Parse a -> Parse a
+ Data.GraphViz.ParserCombinators: optionalQuotedString :: String -> Parse String
+ Data.GraphViz.ParserCombinators: parse :: (Parseable a) => Parse a
+ Data.GraphViz.ParserCombinators: parseAndSpace :: Parse a -> Parse a
+ Data.GraphViz.ParserCombinators: parseBoolField :: String -> Parse Bool
+ Data.GraphViz.ParserCombinators: parseField :: (Parseable a) => String -> Parse a
+ Data.GraphViz.ParserCombinators: parseList :: (Parseable a) => Parse [a]
+ Data.GraphViz.ParserCombinators: quotedParse :: Parse a -> Parse a
+ Data.GraphViz.ParserCombinators: quotedString :: Parse String
+ Data.GraphViz.ParserCombinators: skipToNewline :: Parse ()
+ Data.GraphViz.ParserCombinators: string :: String -> Parse String
+ Data.GraphViz.ParserCombinators: stringBlock :: Parse String
+ Data.GraphViz.ParserCombinators: strings :: [String] -> Parse String
+ Data.GraphViz.ParserCombinators: type Parse a = Parser Char a
+ Data.GraphViz.ParserCombinators: whitespace :: Parse String
+ Data.GraphViz.ParserCombinators: whitespace' :: Parse String
+ Data.GraphViz.Types: HTML :: URL -> GraphID
+ Data.GraphViz.Types: Num :: Double -> GraphID
+ Data.GraphViz.Types: QStr :: QuotedString -> GraphID
+ Data.GraphViz.Types: Str :: String -> GraphID
+ Data.GraphViz.Types: data GraphID
+ Data.GraphViz.Types: graphID :: DotGraph -> Maybe GraphID
+ Data.GraphViz.Types: instance Eq DotEdge
+ Data.GraphViz.Types: instance Eq DotGraph
+ Data.GraphViz.Types: instance Eq DotNode
+ Data.GraphViz.Types: instance Eq GraphID
+ Data.GraphViz.Types: instance Parseable DotEdge
+ Data.GraphViz.Types: instance Parseable DotGraph
+ Data.GraphViz.Types: instance Parseable DotNode
+ Data.GraphViz.Types: instance Parseable GraphID
+ Data.GraphViz.Types: instance Read DotEdge
+ Data.GraphViz.Types: instance Read DotGraph
+ Data.GraphViz.Types: instance Read DotNode
+ Data.GraphViz.Types: instance Read GraphID
+ Data.GraphViz.Types: instance Show GraphID
+ Data.GraphViz.Types: invalidAttributes :: DotGraph -> ([Attribute], [(DotNode, Attribute)], [(DotEdge, Attribute)])
+ Data.GraphViz.Types: isValidGraph :: DotGraph -> Bool
+ Data.GraphViz.Types: makeStrict :: DotGraph -> DotGraph
+ Data.GraphViz.Types: parseDotGraph :: Parse DotGraph
+ Data.GraphViz.Types: setID :: GraphID -> DotGraph -> DotGraph
+ Data.GraphViz.Types: strictGraph :: DotGraph -> Bool
- Data.GraphViz.Attributes: BgColor :: ColorType -> Attribute
+ Data.GraphViz.Attributes: BgColor :: Color -> Attribute
- Data.GraphViz.Attributes: Bold :: StyleType
+ Data.GraphViz.Attributes: Bold :: StyleName
- Data.GraphViz.Attributes: Box3d :: ShapeType
+ Data.GraphViz.Attributes: Box3d :: Shape
- Data.GraphViz.Attributes: BoxShape :: ShapeType
+ Data.GraphViz.Attributes: BoxShape :: Shape
- Data.GraphViz.Attributes: Circle :: ShapeType
+ Data.GraphViz.Attributes: Circle :: Shape
- Data.GraphViz.Attributes: Color :: ColorType -> Attribute
+ Data.GraphViz.Attributes: Color :: (Either Color [Color]) -> Attribute
- Data.GraphViz.Attributes: Component :: ShapeType
+ Data.GraphViz.Attributes: Component :: Shape
- Data.GraphViz.Attributes: Dashed :: StyleType
+ Data.GraphViz.Attributes: Dashed :: StyleName
- Data.GraphViz.Attributes: Diagonals :: StyleType
+ Data.GraphViz.Attributes: Diagonals :: StyleName
- Data.GraphViz.Attributes: DiamondShape :: ShapeType
+ Data.GraphViz.Attributes: DiamondShape :: Shape
- Data.GraphViz.Attributes: Dotted :: StyleType
+ Data.GraphViz.Attributes: Dotted :: StyleName
- Data.GraphViz.Attributes: Doublecircle :: ShapeType
+ Data.GraphViz.Attributes: Doublecircle :: Shape
- Data.GraphViz.Attributes: Doubleoctagon :: ShapeType
+ Data.GraphViz.Attributes: Doubleoctagon :: Shape
- Data.GraphViz.Attributes: Egg :: ShapeType
+ Data.GraphViz.Attributes: Egg :: Shape
- Data.GraphViz.Attributes: Ellipse :: ShapeType
+ Data.GraphViz.Attributes: Ellipse :: Shape
- Data.GraphViz.Attributes: FillColor :: ColorType -> Attribute
+ Data.GraphViz.Attributes: FillColor :: Color -> Attribute
- Data.GraphViz.Attributes: Filled :: StyleType
+ Data.GraphViz.Attributes: Filled :: StyleName
- Data.GraphViz.Attributes: Folder :: ShapeType
+ Data.GraphViz.Attributes: Folder :: Shape
- Data.GraphViz.Attributes: FontColor :: ColorType -> Attribute
+ Data.GraphViz.Attributes: FontColor :: Color -> Attribute
- Data.GraphViz.Attributes: HeadLabel :: String -> Attribute
+ Data.GraphViz.Attributes: HeadLabel :: (Either String URL) -> Attribute
- Data.GraphViz.Attributes: Hexagon :: ShapeType
+ Data.GraphViz.Attributes: Hexagon :: Shape
- Data.GraphViz.Attributes: House :: ShapeType
+ Data.GraphViz.Attributes: House :: Shape
- Data.GraphViz.Attributes: Invhouse :: ShapeType
+ Data.GraphViz.Attributes: Invhouse :: Shape
- Data.GraphViz.Attributes: Invisible :: StyleType
+ Data.GraphViz.Attributes: Invisible :: StyleName
- Data.GraphViz.Attributes: Invtrapezium :: ShapeType
+ Data.GraphViz.Attributes: Invtrapezium :: Shape
- Data.GraphViz.Attributes: Invtriangle :: ShapeType
+ Data.GraphViz.Attributes: Invtriangle :: Shape
- Data.GraphViz.Attributes: Label :: String -> Attribute
+ Data.GraphViz.Attributes: Label :: (Either String URL) -> Attribute
- Data.GraphViz.Attributes: LabelFontColor :: ColorType -> Attribute
+ Data.GraphViz.Attributes: LabelFontColor :: Color -> Attribute
- Data.GraphViz.Attributes: Margin :: Double -> Double -> Attribute
+ Data.GraphViz.Attributes: Margin :: (Either Double Point) -> Attribute
- Data.GraphViz.Attributes: Mcircle :: ShapeType
+ Data.GraphViz.Attributes: Mcircle :: Shape
- Data.GraphViz.Attributes: Mdiamond :: ShapeType
+ Data.GraphViz.Attributes: Mdiamond :: Shape
- Data.GraphViz.Attributes: Msquare :: ShapeType
+ Data.GraphViz.Attributes: Msquare :: Shape
- Data.GraphViz.Attributes: NoShape :: ShapeType
+ Data.GraphViz.Attributes: NoShape :: Shape
- Data.GraphViz.Attributes: Note :: ShapeType
+ Data.GraphViz.Attributes: Note :: Shape
- Data.GraphViz.Attributes: Octagon :: ShapeType
+ Data.GraphViz.Attributes: Octagon :: Shape
- Data.GraphViz.Attributes: Overlap :: Bool -> Attribute
+ Data.GraphViz.Attributes: Overlap :: (Either String Bool) -> Attribute
- Data.GraphViz.Attributes: Pad :: Double -> Double -> Attribute
+ Data.GraphViz.Attributes: Pad :: (Either Double Point) -> Attribute
- Data.GraphViz.Attributes: Page :: Double -> Double -> Attribute
+ Data.GraphViz.Attributes: Page :: Point -> Attribute
- Data.GraphViz.Attributes: Parallelogram :: ShapeType
+ Data.GraphViz.Attributes: Parallelogram :: Shape
- Data.GraphViz.Attributes: PenColor :: ColorType -> Attribute
+ Data.GraphViz.Attributes: PenColor :: Color -> Attribute
- Data.GraphViz.Attributes: Pentagon :: ShapeType
+ Data.GraphViz.Attributes: Pentagon :: Shape
- Data.GraphViz.Attributes: Plaintext :: ShapeType
+ Data.GraphViz.Attributes: Plaintext :: Shape
- Data.GraphViz.Attributes: PointShape :: ShapeType
+ Data.GraphViz.Attributes: PointShape :: Shape
- Data.GraphViz.Attributes: Polygon :: ShapeType
+ Data.GraphViz.Attributes: Polygon :: Shape
- Data.GraphViz.Attributes: Pos :: PointList -> Attribute
+ Data.GraphViz.Attributes: Pos :: (Either Point [Spline]) -> Attribute
- Data.GraphViz.Attributes: RGB :: Word8 -> Word8 -> Word8 -> ColorType
+ Data.GraphViz.Attributes: RGB :: Word8 -> Word8 -> Word8 -> Color
- Data.GraphViz.Attributes: RGBA :: Word8 -> Word8 -> Word8 -> Word8 -> ColorType
+ Data.GraphViz.Attributes: RGBA :: Word8 -> Word8 -> Word8 -> Word8 -> Color
- Data.GraphViz.Attributes: RankDir :: PageDir -> Attribute
+ Data.GraphViz.Attributes: RankDir :: RankDir -> Attribute
- Data.GraphViz.Attributes: Ratio :: Double -> Attribute
+ Data.GraphViz.Attributes: Ratio :: Ratios -> Attribute
- Data.GraphViz.Attributes: Rectangle :: ShapeType
+ Data.GraphViz.Attributes: Rectangle :: Shape
- Data.GraphViz.Attributes: Rotate :: Double -> Attribute
+ Data.GraphViz.Attributes: Rotate :: Int -> Attribute
- Data.GraphViz.Attributes: Rounded :: StyleType
+ Data.GraphViz.Attributes: Rounded :: StyleName
- Data.GraphViz.Attributes: Sep :: Double -> Attribute
+ Data.GraphViz.Attributes: Sep :: (Either Double Point) -> Attribute
- Data.GraphViz.Attributes: Septagon :: ShapeType
+ Data.GraphViz.Attributes: Septagon :: Shape
- Data.GraphViz.Attributes: Shape :: ShapeType -> Attribute
+ Data.GraphViz.Attributes: Shape :: Shape -> Attribute
- Data.GraphViz.Attributes: Size :: Double -> Double -> Attribute
+ Data.GraphViz.Attributes: Size :: Point -> Attribute
- Data.GraphViz.Attributes: Solid :: StyleType
+ Data.GraphViz.Attributes: Solid :: StyleName
- Data.GraphViz.Attributes: Splines :: (Maybe Bool) -> Attribute
+ Data.GraphViz.Attributes: Splines :: (Either Bool String) -> Attribute
- Data.GraphViz.Attributes: Style :: StyleType -> Attribute
+ Data.GraphViz.Attributes: Style :: Style -> Attribute
- Data.GraphViz.Attributes: Tab :: ShapeType
+ Data.GraphViz.Attributes: Tab :: Shape
- Data.GraphViz.Attributes: TailLabel :: String -> Attribute
+ Data.GraphViz.Attributes: TailLabel :: (Either String URL) -> Attribute
- Data.GraphViz.Attributes: Trapezium :: ShapeType
+ Data.GraphViz.Attributes: Trapezium :: Shape
- Data.GraphViz.Attributes: Triangle :: ShapeType
+ Data.GraphViz.Attributes: Triangle :: Shape
- Data.GraphViz.Attributes: Tripleoctagon :: ShapeType
+ Data.GraphViz.Attributes: Tripleoctagon :: Shape
- Data.GraphViz.Attributes: alpha :: ColorType -> Word8
+ Data.GraphViz.Attributes: alpha :: Color -> Word8
- Data.GraphViz.Attributes: blue :: ColorType -> Word8
+ Data.GraphViz.Attributes: blue :: Color -> Word8
- Data.GraphViz.Attributes: green :: ColorType -> Word8
+ Data.GraphViz.Attributes: green :: Color -> Word8
- Data.GraphViz.Attributes: red :: ColorType -> Word8
+ Data.GraphViz.Attributes: red :: Color -> Word8
- Data.GraphViz.Types: DotGraph :: [Attribute] -> [DotNode] -> [DotEdge] -> Bool -> DotGraph
+ Data.GraphViz.Types: DotGraph :: Bool -> Bool -> Maybe GraphID -> [Attribute] -> [DotNode] -> [DotEdge] -> DotGraph
Files
- Changelog +52/−0
- Data/GraphViz.hs +54/−57
- Data/GraphViz/Attributes.hs +1702/−692
- Data/GraphViz/Commands.hs +13/−13
- Data/GraphViz/ParserCombinators.hs +207/−26
- Data/GraphViz/Types.hs +176/−83
- TODO +9/−3
- graphviz.cabal +29/−19
+ Changelog view
@@ -0,0 +1,52 @@+Changes since 2009.5.1+======================++* Fixed a bug where the Show instance and read function for DotEdge+ had the from/to nodes the wrong way round. This was not immediately+ noticed since the Graph -> DotGraph functions created them the wrong+ way round, so for those users who only used these this was not+ apparent. Spotted by Neil Brown.++* Greatly improved Attribute usage: almost all attributes are now+ covered with allowed values.++* Extend DotGraph to include whether a graph is strict or not and if+ it has an ID. Also move the directedGraph field.++* Make "Dot" refer to the actual dot command and DotArrow refer to the+ ArrowType (rather than DotCmd and Dot as before).++* Make the Data.GraphViz.ParserCombinators module available to end+ users again, but not re-exported by Data.GraphViz; it has a warning+ message up the top not to be used. It is there purely for+ documentative purposes.++* Use extensible-exceptions so that base < 4 is once again supported.++* Follow the PVP rather than using dates for versions:+ http://www.haskell.org/haskellwiki/Package_versioning_policy++Changes since 2008.9.20:+========================++* Support polyparse >= 1.1 (as opposed to < 1.3)++* Require base == 4.* (i.e. GHC 6.10.*) due to new exception handling.++* Include functions from Graphalyze-0.5 for running GraphViz commands,+ etc.++* Module re-organisation.++* The Data.GraphViz.ParserCombinators module is no longer available to+ end users.++* Improved Haddock documentation.++Changes since 2008.9.6+======================++* Differentiate between undirected and directed graphs (previously+ only directed graphs were supported).++* Clustering support was added.
Data/GraphViz.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE NamedFieldPuns- , ScopedTypeVariables- #-}- {- | Module : Data.GraphViz Description : GraphViz bindings for Haskell.@@ -16,13 +12,7 @@ Information about GraphViz and the Dot language can be found at: <http://graphviz.org/>-- Note that this module re-exports the "Data.GraphViz.Attributes"- module, which exports a constructor that clashes with- 'Prelude.LT'. As such, you may need to import either this module- or the @Prelude@ qualified or hiding @LT@.-- -}+ -} module Data.GraphViz ( graphToDot@@ -35,33 +25,30 @@ , module Data.GraphViz.Types , module Data.GraphViz.Attributes , module Data.GraphViz.Commands- )- where+ ) where +import Data.GraphViz.Types+import Data.GraphViz.Types.Clustering+import Data.GraphViz.Attributes+import Data.GraphViz.Commands+import Data.GraphViz.ParserCombinators(runParser)+ import Data.Graph.Inductive.Graph-import Data.List-import Data.Function import qualified Data.Set as Set-import Text.ParserCombinators.Poly.Lazy-import Control.Monad+import Control.Arrow((&&&)) import Data.Maybe import qualified Data.Map as Map-import System.IO+import System.IO(hGetContents) import System.IO.Unsafe(unsafePerformIO) -import Data.GraphViz.Types-import Data.GraphViz.Types.Clustering-import Data.GraphViz.Attributes-import Data.GraphViz.Commands- -- ----------------------------------------------------------------------------- -- | Determine if the given graph is undirected or directed. isUndir :: (Ord b, Graph g) => g a b -> Bool-isUndir g = all hasFlip edges+isUndir g = all hasFlip es where- edges = labEdges g- eSet = Set.fromList edges+ es = labEdges g+ eSet = Set.fromList es hasFlip e = Set.member (flippedEdge e) eSet flippedEdge (f,t,l) = (t,f,l) @@ -70,8 +57,8 @@ -- | Convert a graph to GraphViz's /Dot/ format. graphToDot :: (Ord b, Graph gr) => gr a b -> [Attribute] -> (LNode a -> [Attribute]) -> (LEdge b -> [Attribute]) -> DotGraph-graphToDot graph graphAttributes fmtNode fmtEdge- = clusterGraphToDot graph graphAttributes clusterBy fmtCluster fmtNode fmtEdge+graphToDot graph gAttributes fmtNode fmtEdge+ = clusterGraphToDot graph gAttributes clusterBy fmtCluster fmtNode fmtEdge where clusterBy :: LNode a -> NodeCluster () a clusterBy = N@@ -84,17 +71,23 @@ -> [Attribute] -> (LNode a -> NodeCluster c a) -> (c -> [Attribute]) -> (LNode a -> [Attribute]) -> (LEdge b -> [Attribute]) -> DotGraph-clusterGraphToDot graph graphAttributes clusterBy fmtCluster fmtNode fmtEdge- = DotGraph { graphAttributes, graphNodes, graphEdges, directedGraph }+clusterGraphToDot graph gAttrs clusterBy fmtCluster fmtNode fmtEdge+ = DotGraph { strictGraph = False+ , directedGraph = dirGraph+ , graphID = Nothing+ , graphAttributes = gAttrs+ , graphNodes = ns+ , graphEdges = es+ } where- graphNodes = clustersToNodes clusterBy fmtCluster fmtNode graph- directedGraph = not $ isUndir graph- graphEdges = catMaybes . map mkDotEdge . labEdges $ graph- mkDotEdge e@(f,t,_) = if (directedGraph || f <= t)- then Just $ DotEdge {edgeHeadNodeID = t- ,edgeTailNodeID = f- ,edgeAttributes = fmtEdge e- ,directedEdge = directedGraph}+ dirGraph = not $ isUndir graph+ ns = clustersToNodes clusterBy fmtCluster fmtNode graph+ es = mapMaybe mkDotEdge . labEdges $ graph+ mkDotEdge e@(f,t,_) = if dirGraph || f <= t+ then Just DotEdge {edgeHeadNodeID = f+ ,edgeTailNodeID = t+ ,edgeAttributes = fmtEdge e+ ,directedEdge = dirGraph} else Nothing -- -----------------------------------------------------------------------------@@ -105,31 +98,35 @@ -- | Run the graph via dot to get positional information and then -- combine that information back into the original graph. -- Note that this doesn't support graphs with clusters.-graphToGraph :: forall gr a b . (Ord b, Graph gr) =>- gr a b -> [Attribute] -> (LNode a -> [Attribute]) -> (LEdge b -> [Attribute]) -> IO (gr (AttributeNode a) (AttributeEdge b))-graphToGraph gr graphAttributes fmtNode fmtEdge- = do { out <- graphvizWithHandle command dot DotOutput hGetContents- ; let res = fromJust out- ; (length res) `seq` return ()- ; return $ rebuildGraphWithAttributes res- }+graphToGraph :: (Ord b, Graph gr) => gr a b -> [Attribute]+ -> (LNode a -> [Attribute]) -> (LEdge b -> [Attribute])+ -> IO (gr (AttributeNode a) (AttributeEdge b))+graphToGraph gr gAttributes fmtNode fmtEdge+ = do output <- graphvizWithHandle command dot DotOutput hGetContents+ let res = fromJust output+ length res `seq` return ()+ return $ rebuildGraphWithAttributes res where undirected = isUndir gr command = if undirected then undirCommand else dirCommand- dot = graphToDot gr graphAttributes fmtNode fmtEdge- rebuildGraphWithAttributes :: String -> gr (AttributeNode a) (AttributeEdge b)+ dot = graphToDot gr gAttributes fmtNode fmtEdge rebuildGraphWithAttributes dotResult = mkGraph lnodes ledges where- lnodes = map (\(n, l) -> (n, (fromJust $ Map.lookup n nodeMap, l))) . labNodes $ gr- ledges = map createEdges . labEdges $ gr- (DotGraph { graphEdges, graphNodes }) = fst . runParser readDotGraph $ dotResult- nodeMap = Map.fromList . map (\n -> (nodeID n, nodeAttributes n)) $ graphNodes- edgeMap = Map.fromList . map (\e -> ((edgeTailNodeID e, edgeHeadNodeID e), edgeAttributes e)) $ graphEdges- createEdges (f,t,l) = if (undirected && f > t)- then (f,t,getLabel (t,f))- else (f,t,getLabel (f,t))+ lnodes = map (\(n, l) -> (n, (fromJust $ Map.lookup n nodeMap, l)))+ $ labNodes gr+ ledges = map createEdges $ labEdges gr+ createEdges (f, t, l) = if undirected && f > t+ then (f, t, getLabel (t,f))+ else (f, t, getLabel (f,t)) where- getLabel c = (fromJust $ Map.lookup c edgeMap,l)+ getLabel c = (fromJust $ Map.lookup c edgeMap, l)+ DotGraph { graphNodes = ns, graphEdges = es}+ = fst . runParser parseDotGraph $ dotResult+ nodeMap = Map.fromList $ map (nodeID &&& nodeAttributes) ns+ edgeMap = Map.fromList $ map (\e -> ( ( edgeTailNodeID e+ , edgeHeadNodeID e)+ , edgeAttributes e)+ ) es -- | Pass the plain graph through 'graphToGraph'. This is an @IO@ action, -- however since the state doesn't change it's safe to use 'unsafePerformIO'
Data/GraphViz/Attributes.hs view
@@ -1,692 +1,1702 @@-{-# LANGUAGE NamedFieldPuns- , ScopedTypeVariables- #-}--{- |- Module : Data.GraphViz.Attributes- Description : Definition of the GraphViz attributes.- Copyright : (c) Matthew Sackman, Ivan Lazar Miljenovic- License : 3-Clause BSD-style- Maintainer : Ivan.Miljenovic@gmail.com-- This module defines the various attributes that different parts of- a GraphViz graph can have. Note that when using this module, you- may need to either import it or @Prelude@ qualified or hiding- @LT@, as this module exports a constructor with the same name.- -}--module Data.GraphViz.Attributes where--import Prelude hiding (LT)--import Data.Word-import Numeric-import Text.ParserCombinators.Poly.Lazy-import Control.Monad-import Data.Maybe--import Data.GraphViz.ParserCombinators--data ArrowType = Normal | Inv- | Dot | InvDot- | ODot | InvODot- | NoArrow | Tee- | Empty | InvEmpty- | Diamond | ODiamond- | EDiamond | Crow- | Box | OBox- | Open | HalfOpen- | Vee- deriving (Eq)--instance Show ArrowType where- show Normal = "normal"- show Inv = "inv"- show Dot = "dot"- show InvDot = "invdot"- show ODot = "odot"- show InvODot = "invodot"- show NoArrow = "none"- show Tee = "tee"- show Empty = "empty"- show InvEmpty = "invempty"- show Diamond = "diamond"- show ODiamond = "odiamond"- show EDiamond = "ediamond"- show Crow = "crow"- show Box = "box"- show OBox = "obox"- show Open = "open"- show HalfOpen = "halfopen"- show Vee = "vee"--readArrowType :: Parser Char ArrowType-readArrowType- = oneOf [ optionalQuotedString "normal" >> return Normal- , optionalQuotedString "inv" >> return Inv- , optionalQuotedString "dot" >> return Dot- , optionalQuotedString "invdot" >> return InvDot- , optionalQuotedString "odot" >> return ODot- , optionalQuotedString "invodot" >> return InvODot- , optionalQuotedString "noarrow" >> return NoArrow- , optionalQuotedString "tee" >> return Tee- , optionalQuotedString "empty" >> return Empty- , optionalQuotedString "invempty" >> return InvEmpty- , optionalQuotedString "diamond" >> return Diamond- , optionalQuotedString "odiamond" >> return ODiamond- , optionalQuotedString "ediamond" >> return EDiamond- , optionalQuotedString "crow" >> return Crow- , optionalQuotedString "box" >> return Box- , optionalQuotedString "obox" >> return OBox- , optionalQuotedString "open" >> return Open- , optionalQuotedString "halfopen" >> return HalfOpen- , optionalQuotedString "vee" >> return Vee- ]--data ColorType = RGB { red :: Word8- , green :: Word8- , blue :: Word8- }- | RGBA { red :: Word8- , green :: Word8- , blue :: Word8- , alpha :: Word8- }- deriving (Eq)--instance Show ColorType where- show (RGB { red, green, blue })- = show $ '#' : foldr showWord8Pad "" [red, green, blue]- show (RGBA { red, green, blue, alpha })- = show $ '#' : foldr showWord8Pad "" [red, green, blue, alpha]--showWord8Pad :: Word8 -> String -> String-showWord8Pad w s = padding ++ simple ++ s- where- simple = showHex w ""- padding = replicate count '0'- count = (2 - (findCols 1 w))- findCols :: Int -> Word8 -> Int- findCols c n- | n < 16 = c- | otherwise = findCols (c+1) (n `div` 16)--readColorType :: Parser Char ColorType-readColorType- = do { string "\"#"- ; digits <- many $ noneOf ['"']- ; char '"'- ; let c = readHexPairs digits- ; return $ case c of- [r,g,b]- -> RGB r g b- [r,g,b,a]- -> RGBA r g b a- _ -> error $ "Unexpected pairs: " ++ show c- }- where- readHexPairs :: String -> [Word8]- readHexPairs [] = []- readHexPairs (h1:h2:h')- = let [(n, [])] = readHex [h1,h2] in n : readHexPairs h'- readHexPairs c = error $ "Error in readHexPairs: " ++ (show c)--data DirType = Forward | Back | Both | None- deriving (Eq)--instance Show DirType where- show Forward = "forward"- show Back = "back"- show Both = "both"- show None = "none"--readDirType :: Parser Char DirType-readDirType- = oneOf [optionalQuotedString "forward" >> return Forward- ,optionalQuotedString "back" >> return Back- ,optionalQuotedString "both" >> return Both- ,optionalQuotedString "none" >> return None- ]--data OutputMode = BreadthFirst | NodesFirst | EdgesFirst- deriving (Eq)--instance Show OutputMode where- show BreadthFirst = "breadthfirst"- show NodesFirst = "nodesfirst"- show EdgesFirst = "edgesfirst"--readOutputMode :: Parser Char OutputMode-readOutputMode- = oneOf [ optionalQuotedString "breadthfirst" >> return BreadthFirst- , optionalQuotedString "nodesfirst" >> return NodesFirst- , optionalQuotedString "edgesfirst" >> return EdgesFirst- ]--data PageDir = BL | BR | TL | TR | RB | RT | LB | LT- deriving (Eq)--instance Show PageDir where- show BL = "BL"- show BR = "BR"- show TL = "TL"- show TR = "TR"- show RB = "RB"- show RT = "RT"- show LB = "LB"- show LT = "LT"--readPageDir :: Parser Char PageDir-readPageDir- = oneOf [ optionalQuotedString "BL" >> return BL- , optionalQuotedString "BR" >> return BR- , optionalQuotedString "TL" >> return TL- , optionalQuotedString "TR" >> return TR- , optionalQuotedString "RB" >> return RB- , optionalQuotedString "RT" >> return RT- , optionalQuotedString "LB" >> return LB- , optionalQuotedString "LT" >> return LT- ]--data ShapeType- = BoxShape- | Polygon- | Ellipse- | Circle- | PointShape- | Egg- | Triangle- | Plaintext- | DiamondShape- | Trapezium- | Parallelogram- | House- | Pentagon- | Hexagon- | Septagon- | Octagon- | Doublecircle- | Doubleoctagon- | Tripleoctagon- | Invtriangle- | Invtrapezium- | Invhouse- | Mdiamond- | Msquare- | Mcircle- | Rectangle- | NoShape- | Note- | Tab- | Folder- | Box3d- | Component- deriving (Eq)--instance Show ShapeType where- show BoxShape = "box"- show Polygon = "polygon"- show Ellipse = "ellipse"- show Circle = "circle"- show PointShape = "point"- show Egg = "egg"- show Triangle = "triangle"- show Plaintext = "plaintext"- show DiamondShape = "diamond"- show Trapezium = "trapezium"- show Parallelogram = "parallelogram"- show House = "house"- show Pentagon = "pentagon"- show Hexagon = "hexagon"- show Septagon = "septagon"- show Octagon = "octagon"- show Doublecircle = "doublecircle"- show Doubleoctagon = "doubleoctagon"- show Tripleoctagon = "tripleoctagon"- show Invtriangle = "invtriangle"- show Invtrapezium = "invtrapezium"- show Invhouse = "invhouse"- show Mdiamond = "mdiamond"- show Msquare = "msquare"- show Mcircle = "mcircle"- show Rectangle = "rectangle"- show NoShape = "none"- show Note = "note"- show Tab = "tab"- show Folder = "folder"- show Box3d = "box3d"- show Component = "component"--readShapeType :: Parser Char ShapeType-readShapeType- = oneOf [ optionalQuotedString "box" >> return BoxShape- , optionalQuotedString "polygon" >> return Polygon- , optionalQuotedString "ellipse" >> return Ellipse- , optionalQuotedString "circle" >> return Circle- , optionalQuotedString "point" >> return PointShape- , optionalQuotedString "egg" >> return Egg- , optionalQuotedString "triangle" >> return Triangle- , optionalQuotedString "plaintext" >> return Plaintext- , optionalQuotedString "diamond" >> return DiamondShape- , optionalQuotedString "trapezium" >> return Trapezium- , optionalQuotedString "parallelogram" >> return Parallelogram- , optionalQuotedString "house" >> return House- , optionalQuotedString "pentagon" >> return Pentagon- , optionalQuotedString "hexagon" >> return Hexagon- , optionalQuotedString "septagon" >> return Septagon- , optionalQuotedString "octagon" >> return Octagon- , optionalQuotedString "doublecircle" >> return Doublecircle- , optionalQuotedString "doubleoctagon" >> return Doubleoctagon- , optionalQuotedString "tripleoctagon" >> return Tripleoctagon- , optionalQuotedString "invtriangle" >> return Invtriangle- , optionalQuotedString "invtrapezium" >> return Invtrapezium- , optionalQuotedString "invhouse" >> return Invhouse- , optionalQuotedString "mdiamond" >> return Mdiamond- , optionalQuotedString "msquare" >> return Msquare- , optionalQuotedString "mcircle" >> return Mcircle- , optionalQuotedString "rectangle" >> return Rectangle- , optionalQuotedString "none" >> return NoShape- , optionalQuotedString "note" >> return Note- , optionalQuotedString "tab" >> return Tab- , optionalQuotedString "folder" >> return Folder- , optionalQuotedString "box3d" >> return Box3d- , optionalQuotedString "component" >> return Component- ]--data StyleType = Filled | Invisible | Diagonals | Rounded | Dashed | Dotted | Solid | Bold- deriving (Eq)--instance Show StyleType where- show Filled = "filled"- show Invisible = "invisible"- show Diagonals = "diagonals"- show Rounded = "rounded"- show Dashed = "dashed"- show Dotted = "dotted"- show Solid = "solid"- show Bold = "bold"--readStyleType :: Parser Char StyleType-readStyleType- = oneOf [ optionalQuotedString "filled" >> return Filled- , optionalQuotedString "invisible" >> return Invisible- , optionalQuotedString "diagonals" >> return Diagonals- , optionalQuotedString "rounded" >> return Rounded- , optionalQuotedString "dashed" >> return Dashed- , optionalQuotedString "dotted" >> return Dotted- , optionalQuotedString "solid" >> return Solid- , optionalQuotedString "bold" >> return Bold- ]--data Point = Point Int Int- | PointD Double Double- deriving (Eq)--newtype PointList = PointList [Point]- deriving (Eq)--instance Show Point where- show (Point x y) = show $ (show x) ++ (',':(show y))- show (PointD x y) = show $ (show x) ++ (',':(show y))--instance Show PointList where- show (PointList points) = show $ case foldr s "" points of- [] -> ""- str -> tail str- where- s (Point x y) acc = ' ':((show x) ++ (',':((show y) ++ acc)))- s (PointD x y) acc = ' ':((show x) ++ (',':((show y) ++ acc)))--readPoint :: Parser Char Point-readPoint = char '"' >> oneOf [readPointI, readPointD]- where- readPointI = do { x <- number- ; char ','- ; y <- number- ; char '"'- ; return $ Point x y- }- readPointD = do { x <- floatingNumber- ; char ','- ; y <- floatingNumber- ; char '"'- ; return $ PointD x y- }--readPointList :: Parser Char PointList-readPointList- = do { char '"'- ; points <- many pointPair- ; char '"'- ; return $ PointList points- }- where- pointPair- = do { x <- number- ; char ','- ; y <- number- ; optional (char ' ')- ; return $ Point x y- }--data Rect = Rect Point Point- deriving (Eq)--instance Show Rect where- show (Rect (Point x1 y1) (Point x2 y2))- = show $ (show x1) ++ (',': ((show y1) ++ (',': ((show x2) ++ (',': (show y2))))))- show (Rect (Point x1 y1) (PointD x2 y2))- = show $ (show x1) ++ (',': ((show y1) ++ (',': ((show x2) ++ (',': (show y2))))))- show (Rect (PointD x1 y1) (Point x2 y2))- = show $ (show x1) ++ (',': ((show y1) ++ (',': ((show x2) ++ (',': (show y2))))))- show (Rect (PointD x1 y1) (PointD x2 y2))- = show $ (show x1) ++ (',': ((show y1) ++ (',': ((show x2) ++ (',': (show y2))))))--readRect :: Parser Char Rect-readRect = do { char '"'- ; x1 <- number- ; char ','- ; y1 <- number- ; char ','- ; x2 <- number- ; char ','- ; y2 <- number- ; char '"'- ; return (Rect (Point x1 y1) (Point x2 y2))- }--data ScaleType = Scale | NoScale | FitX | FitY- deriving (Eq)--instance Show ScaleType where- show Scale = "true"- show NoScale = "false"- show FitX = "width"- show FitY = "height"--readScaleType :: Parser Char ScaleType-readScaleType = oneOf [ optionalQuotedString "true" >> return Scale- , optionalQuotedString "false" >> return NoScale- , optionalQuotedString "width" >> return FitX- , optionalQuotedString "height" >> return FitY- ]--data Justification = JLeft | JRight | JCenter- deriving (Eq)--instance Show Justification where- show JLeft = "l"- show JRight = "r"- show JCenter = "c"--readJustification :: Parser Char Justification-readJustification = oneOf [ optionalQuotedString "l" >> return JLeft- , optionalQuotedString "r" >> return JRight- , optionalQuotedString "c" >> return JCenter- ]--data VerticalPlacement = VTop | VCenter | VBottom- deriving (Eq)--instance Show VerticalPlacement where- show VTop = "t"- show VCenter = "c"- show VBottom = "b"--readVerticalPlacement :: Parser Char VerticalPlacement-readVerticalPlacement- = oneOf [ optionalQuotedString "t" >> return VTop- , optionalQuotedString "c" >> return VCenter- , optionalQuotedString "b" >> return VBottom- ]--data Attribute- = ArrowHead ArrowType- | ArrowSize Double- | ArrowTail ArrowType- | Bb Rect- | BgColor ColorType- | Center Bool- | Color ColorType- | Concentrate Bool- | Constraint Bool- | Decorate Bool- | DefaultDist Double- | Dir DirType- | Dpi Double- | FillColor ColorType- | FixedSize Bool- | FontColor ColorType- | FontName String- | FontSize Double- | Group String- | HeadClip Bool- | HeadLabel String- | Height Double- | Image String- | ImageScale ScaleType- | Label String- | LabelAngle Double- | LabelDistance Double- | LabelFloat Bool- | LabelFontColor ColorType- | LabelFontName String- | LabelFontSize Double- | LabelJust Justification- | LabelLoc VerticalPlacement- | Landscape Bool- | Len Double- | Margin Double Double- | MinDist Double- | Minlen Double- | Nodesep Double- | NoJustify Bool- | Normalize Bool- | Orientation Double- | OutputOrder OutputMode- | Overlap Bool- | Pad Double Double- | Page Double Double- | PageDir PageDir- | PenColor ColorType- | Pos PointList- | Quantum Double- | RankDir PageDir- | RankSep Double- | Ratio Double- | Regular Bool- | Rotate Double- | SameHead String- | SameTail String- | Sep Double- | Shape ShapeType- | Sides Int- | Size Double Double- | Skew Double- | Splines (Maybe Bool)- | Style StyleType- | TailClip Bool- | TailLabel String- | Weight Double- | Width Double- | Unknown String String- deriving (Eq)--instance Show Attribute where- show (ArrowHead arrowtype) = "arrowhead=" ++ (show arrowtype)- show (ArrowSize double) = "arrowsize=" ++ (show double)- show (ArrowTail arrowtype) = "arrowtail=" ++ (show arrowtype)- show (Bb rect) = "bb=" ++ (show rect)- show (BgColor colortype) = "bgcolor=" ++ (show colortype)- show (Center bool) = "center=" ++ (show bool)- show (Color colortype) = "color=" ++ (show colortype)- show (Concentrate bool) = "concentrate=" ++ (show bool)- show (Constraint bool) = "constraint=" ++ (show bool)- show (Decorate bool) = "decorate=" ++ (show bool)- show (DefaultDist double) = "defaultdist=" ++ (show double)- show (Dir dirtype) = "dir=" ++ (show dirtype)- show (Dpi double) = "dpi=" ++ (show double)- show (FillColor colortype) = "fillcolor=" ++ (show colortype)- show (FixedSize bool) = "fixedsize=" ++ (show bool)- show (FontColor colortype) = "fontcolor=" ++ (show colortype)- show (FontName string) = "fontname=" ++ (show string)- show (FontSize double) = "fontsize=" ++ (show double)- show (Group string) = "group=" ++ (show string)- show (HeadClip bool) = "headclip=" ++ (show bool)- show (HeadLabel string) = "headlabel=" ++ (show string)- show (Height double) = "height=" ++ (show double)- show (Image string) = "image=" ++ (show string)- show (ImageScale scaletype) = "imagescale=" ++ (show scaletype)- show (Label string) = "label=" ++ (show string)- show (LabelAngle double) = "labelangle=" ++ (show double)- show (LabelDistance double) = "labeldistance=" ++ (show double)- show (LabelFloat bool) = "labelfloat=" ++ (show bool)- show (LabelFontColor colortype) = "labelfontcolor=" ++ (show colortype)- show (LabelFontName string) = "labelfontname=" ++ (show string)- show (LabelFontSize double) = "labelfontsize=" ++ (show double)- show (LabelJust justification) = "labeljust=" ++ (show justification)- show (LabelLoc verticalplacement) = "labelloc=" ++ (show verticalplacement)- show (Landscape bool) = "landscape=" ++ (show bool)- show (Len double) = "len=" ++ (show double)- show (Margin double1 double2) = "margin=" ++ (show $ PointD double1 double2)- show (MinDist double) = "mindist=" ++ (show double)- show (Minlen double) = "minlen=" ++ (show double)- show (Nodesep double) = "nodesep=" ++ (show double)- show (NoJustify bool) = "nojustify=" ++ (show bool)- show (Normalize bool) = "normalize=" ++ (show bool)- show (Orientation double) = "orientation=" ++ (show double)- show (OutputOrder outputmode) = "outputorder=" ++ (show outputmode)- show (Overlap bool) = "overlap=" ++ (show bool)- show (Pad double1 double2) = "pad=" ++ (show $ PointD double1 double2)- show (Page double1 double2) = "page=" ++ (show $ PointD double1 double2)- show (PageDir pagedir) = "pagedir=" ++ (show pagedir)- show (PenColor colortype) = "pencolor=" ++ (show colortype)- show (Pos pointlist) = "pos=" ++ (show pointlist)- show (Quantum double) = "quantum=" ++ (show double)- show (RankDir pagedir) = "rankdir=" ++ (show pagedir)- show (RankSep double) = "ranksep=" ++ (show double)- show (Ratio double) = "ratio=" ++ (show double)- show (Regular bool) = "regular=" ++ (show bool)- show (Rotate double) = "rotate=" ++ (show double)- show (SameHead string) = "samehead=" ++ (show string)- show (SameTail string) = "sametail=" ++ (show string)- show (Sep double) = "sep=" ++ (show double)- show (Shape shapetype) = "shape=" ++ (show shapetype)- show (Sides int) = "sides=" ++ (show int)- show (Size double1 double2) = "size=" ++ (show $ PointD double1 double2)- show (Skew double) = "skew=" ++ (show double)- show (Splines maybebool) = "splines=" ++ (show (fromMaybe [] (liftM show maybebool)))- show (Style styletype) = "style=" ++ (show styletype)- show (TailClip bool) = "tailclip=" ++ (show bool)- show (TailLabel string) = "taillabel=" ++ (show string)- show (Weight double) = "weight=" ++ (show double)- show (Width double) = "width=" ++ (show double)- show (Unknown key value) = (show key) ++ ('=':(show . show $ value))--readBool :: Parser Char Bool-readBool = oneOf [ (optionalQuotedString "true" >> return True)- , (optionalQuotedString "false" >> return False)- , (optionalQuotedString "True" >> return True)- , (optionalQuotedString "False" >> return False)- ]--readString :: Parser Char String-readString = oneOf [quoted, nonquoted]- where- quoted = do { char '"'- ; str <- liftM concat . many . oneOf $ [nonescaped, escapedPair]- ; char '"'- ; return str- }- nonquoted = many $ noneOf ['"', ' ', ',', '\t', '\n', '\r', ']']- escapedPair = do { char '\\'- ; oneOf [ char '"' >> return "\""- , char 't' >> return "\t"- , char 'n' >> return "\n"- , char 'r' >> return "\r"- , satisfy (const True) >>= \c -> return ['\\', c]- ]- }- nonescaped = liftM (: []) . noneOf $ ['\\', '"']--readAttribute :: Parser Char Attribute-readAttribute- = oneOf- [ string "arrowhead=" >> readArrowType >>= return . ArrowHead- , string "arrowsize=" >> optionalQuoted floatingNumber >>= return . ArrowSize- , string "arrowtail=" >> readArrowType >>= return . ArrowTail- , string "bb=" >> readRect >>= return . Bb- , string "bgcolor=" >> readColorType >>= return . BgColor- , string "center=" >> readBool >>= return . Center- , string "color=" >> readColorType >>= return . Color- , string "concentrate=" >> readBool >>= return . Concentrate- , string "constraint=" >> readBool >>= return . Constraint- , string "decorate=" >> readBool >>= return . Decorate- , string "defaultdist=" >> optionalQuoted floatingNumber >>= return . DefaultDist- , string "dir=" >> readDirType >>= return . Dir- , string "dpi=" >> optionalQuoted floatingNumber >>= return . Dpi- , string "fillcolor=" >> readColorType >>= return . FillColor- , string "fixedsize=" >> readBool >>= return . FixedSize- , string "fontcolor=" >> readColorType >>= return . FontColor- , string "fontname=" >> readString >>= return . FontName- , string "fontsize=" >> optionalQuoted floatingNumber >>= return . FontSize- , string "group=" >> readString >>= return . Group- , string "headclip=" >> readBool >>= return . HeadClip- , string "headlabel=" >> readString >>= return . HeadLabel- , string "height=" >> optionalQuoted floatingNumber >>= return . Height- , string "image=" >> readString >>= return . Image- , string "imagescale=" >> readScaleType >>= return . ImageScale- , string "label=" >> readString >>= return . Label- , string "labelangle=" >> optionalQuoted floatingNumber >>= return . LabelAngle- , string "labeldistance=" >> optionalQuoted floatingNumber >>= return . LabelDistance- , string "labelfloat=" >> readBool >>= return . LabelFloat- , string "labelfontcolor=" >> readColorType >>= return . LabelFontColor- , string "labelfontname=" >> readString >>= return . LabelFontName- , string "labelfontsize=" >> optionalQuoted floatingNumber >>= return . LabelFontSize- , string "labeljust=" >> readJustification >>= return . LabelJust- , string "labelloc=" >> readVerticalPlacement >>= return . LabelLoc- , string "landscape=" >> readBool >>= return . Landscape- , string "len=" >> optionalQuoted floatingNumber >>= return . Len- , string "margin=" >> readPoint >>= \(PointD x y) -> return $ Margin x y- , string "mindist=" >> optionalQuoted floatingNumber >>= return . MinDist- , string "minlen=" >> optionalQuoted floatingNumber >>= return . Minlen- , string "nodesep=" >> optionalQuoted floatingNumber >>= return . Nodesep- , string "nojustify=" >> readBool >>= return . NoJustify- , string "normalize=" >> readBool >>= return . Normalize- , string "orientation=" >> optionalQuoted floatingNumber >>= return . Orientation- , string "outputorder=" >> readOutputMode >>= return . OutputOrder- , string "overlap=" >> readBool >>= return . Overlap- , string "pad=" >> readPoint >>= \(PointD x y) -> return $ Pad x y- , string "page=" >> readPoint >>= \(PointD x y) -> return $ Page x y- , string "pagedir=" >> readPageDir >>= return . PageDir- , string "pencolor=" >> readColorType >>= return . PenColor- , string "pos=" >> readPointList >>= return . Pos- , string "quantum=" >> optionalQuoted floatingNumber >>= return . Quantum- , string "rankdir=" >> readPageDir >>= return . RankDir- , string "ranksep=" >> optionalQuoted floatingNumber >>= return . RankSep- , string "ratio=" >> optionalQuoted floatingNumber >>= return . Ratio- , string "regular=" >> readBool >>= return . Regular- , string "rotate=" >> optionalQuoted floatingNumber >>= return . Rotate- , string "samehead=" >> readString >>= return . SameHead- , string "sametail=" >> readString >>= return . SameTail- , string "sep=" >> optionalQuoted floatingNumber >>= return . Sep- , string "shape=" >> readShapeType >>= return . Shape- , string "sides=" >> optionalQuoted number >>= return . Sides- , string "size=" >> readPoint >>= \(PointD x y) -> return $ Size x y- , string "skew=" >> optionalQuoted floatingNumber >>= return . Skew- , string "splines=" >> (oneOf [(string "\"\"" >> return Nothing), readBool >>= return . Just]) >>= return . Splines- , string "style=" >> readStyleType >>= return . Style- , string "tailclip=" >> readBool >>= return . TailClip- , string "taillabel=" >> readString >>= return . TailLabel- , string "weight=" >> optionalQuoted floatingNumber >>= return . Weight- , string "width=" >> optionalQuoted floatingNumber >>= return . Width- , many (noneOf ['=', '"', ' ', ',', '\t', '\n', '\r', ']']) >>= \key -> char '=' >> readString >>= return . Unknown key- ]--readAttributesList :: Parser Char [Attribute]-readAttributesList = do { char '['- ; as <- many (optional whitespace >> readAttribute >>= \a -> optional whitespace >> optional (char ',') >> return a)- ; optional whitespace- ; char ']'- ; return as- }+{- |+ Module : Data.GraphViz.Attributes+ Description : Definition of the GraphViz attributes.+ Copyright : (c) Matthew Sackman, Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module defines the various attributes that different parts of+ a GraphViz graph can have. These attributes are based on the+ documentation found at:++ <http://graphviz.org/doc/info/attrs.html>++ For more information on usage, etc. please see that document.++ A summary of known current constraints\/limitations\/differences:++ * Parsing of quoted strings might not always work if they are a+ sub-part of another Attribute (e.g. a quoted name in 'LayerList').+ In fact, parsing with quotes is iffy for everything; specifically+ when they are and aren't allowed.++ * 'ColorScheme' is ignored when parsing 'Color' values++ * ColorList and PointfList are defined as actual lists (but+ 'LayerList' is not).++ * A lot of values have a possible value of @"none"@. These now+ have custom constructors. In fact, most constructors have been+ expanded upon to give an idea of what they represent rather than+ using generic terms.++ * @PointF@ and 'Point' have been combined, and feature support for pure+ 'Int'-based co-ordinates as well as 'Double' ones (i.e. no floating+ point-only points for Point). The optional '!' and third value+ for Point are not available.++ * 'Rect' uses two 'Point' values to denote the lower-left and+ top-right corners.++ * The two 'LabelLoc' attributes have been combined.++ * The defined 'LayerSep' is not used to parse 'LayerRange' or+ 'LayerList'; the default (@[' ', ':', '\t']@) is instead used.++ * @SplineType@ has been replaced with @['Spline']@.++ * Only polygon-based 'Shape's are available.++ * Device-dependent 'StyleName' values are not available.++ * 'PortPos' only has the 'CompassPoint' option, not+ @PortName[:CompassPoint]@ (since record shapes aren't allowed,+ and parsing HTML-like labels could be problematic).++ * Not every 'Attribute' is fully documented/described. In+ particular, a lot of them are listed as having a 'String' value,+ when actually only certain Strings are allowed.++ -}++module Data.GraphViz.Attributes where++import Data.GraphViz.ParserCombinators++import Data.Char(isDigit, isHexDigit)+import Data.Word+import Numeric+import Control.Monad+import Data.Maybe++-- -----------------------------------------------------------------------------++{- |++ 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.++ Note also that the default values are taken from the specification+ page listed above, and might not correspond fully with the names of+ the permitted values.+-}+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 URL -- ^ /Valid for/: ENGC; /Default/: \<none\>; /Notes/: svg, postscript, map only+ | 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+ | Bb Rect -- ^ /Valid for/: G; /Notes/: write only+ | BgColor Color -- ^ /Valid for/: GC; /Default/: \<none\>+ | Center Bool -- ^ /Valid for/: G; /Default/: false+ | Charset String -- ^ /Valid for/: G; /Default/: \"UTF-8\"+ | ClusterRank ClusterMode -- ^ /Valid for/: G; /Default/: local; /Notes/: dot only+ | Color (Either Color [Color]) -- ^ /Valid for/: ENC; /Default/: black+ | ColorScheme String -- ^ /Valid for/: ENCG; /Default/: \"\"+ | Comment String -- ^ /Valid for/: ENG; /Default/: \"\"+ | Compound Bool -- ^ /Valid for/: G; /Default/: false; /Notes/: dot only+ | Concentrate Bool -- ^ /Valid for/: G; /Default/: false+ | Constraint Bool -- ^ /Valid for/: E; /Default/: true; /Notes/: dot only+ | Decorate Bool -- ^ /Valid for/: E; /Default/: false+ | DefaultDist Double -- ^ /Valid for/: G; /Default/: 1+(avg. len)*sqrt(|V|); /Minimum/: epsilon; /Notes/: neato only+ | Dim Int -- ^ /Valid for/: G; /Default/: 2; /Minimum/: 2; /Notes/: sfdp, fdp, neato only+ | Dimen Int -- ^ /Valid for/: G; /Default/: 2; /Minimum/: 2; /Notes/: sfdp, fdp, neato only+ | Dir DirType -- ^ /Valid for/: E; /Default/: forward(directed)/none(undirected)+ | DirEdgeConstraints (Either String Bool) -- ^ /Valid for/: G; /Default/: false; /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+ | EdgeURL URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | EdgeHref URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | EdgeTarget String -- ^ /Valid for/: E; /Default/: \<none\>; /Notes/: svg, map only+ | EdgeTooltip String -- ^ /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 (Either Double Point) -- ^ /Valid for/: G; /Default/: +3; /Notes/: not dot+ | FillColor Color -- ^ /Valid for/: NC; /Default/: lightgrey(nodes) | black(clusters)+ | FixedSize Bool -- ^ /Valid for/: N; /Default/: false+ | FontColor Color -- ^ /Valid for/: ENGC; /Default/: black+ | FontName String -- ^ /Valid for/: ENGC; /Default/: \"Times-Roman\"+ | FontNames String -- ^ /Valid for/: G; /Default/: \"\"; /Notes/: svg only+ | FontPath String -- ^ /Valid for/: G; /Default/: system-dependent+ | FontSize Double -- ^ /Valid for/: ENGC; /Default/: 14.0; /Minimum/: 1.0+ | Group String -- ^ /Valid for/: N; /Default/: \"\"; /Notes/: dot only+ | HeadURL URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | HeadClip Bool -- ^ /Valid for/: E; /Default/: true+ | HeadHref URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | HeadLabel (Either String URL) -- ^ /Valid for/: E; /Default/: \"\"+ | HeadPort PortPos -- ^ /Valid for/: E; /Default/: center+ | HeadTarget QuotedString -- ^ /Valid for/: E; /Default/: \<none\>; /Notes/: svg, map only+ | HeadTooltip QuotedString -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, cmap only+ | Height Double -- ^ /Valid for/: N; /Default/: 0.5; /Minimum/: 0.02+ | Href URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, postscript, map only+ | ID (Either String URL) -- ^ /Valid for/: GNE; /Default/: \"\"; /Notes/: svg, postscript, map only+ | Image String -- ^ /Valid for/: N; /Default/: \"\"+ | ImageScale ScaleType -- ^ /Valid for/: N; /Default/: false+ | Label (Either String URL) -- ^ /Valid for/: ENGC; /Default/: \"\N\" (nodes) | \"\" (otherwise)+ | LabelURL URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | 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+ | LabelFontColor Color -- ^ /Valid for/: E; /Default/: black+ | LabelFontName String -- ^ /Valid for/: E; /Default/: \"Times-Roman\"+ | LabelFontSize Double -- ^ /Valid for/: E; /Default/: 14.0; /Minimum/: 1.0+ | LabelHref URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | LabelJust Justification -- ^ /Valid for/: GC; /Default/: \"c\"+ | LabelLoc VerticalPlacement -- ^ /Valid for/: GCN; /Default/: \"t\"(clusters) | \"b\"(root graphs) | \"c\"(clusters)+ | LabelTarget String -- ^ /Valid for/: E; /Default/: \<none\>; /Notes/: svg, map only+ | LabelTooltip String -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, cmap only+ | Landscape Bool -- ^ /Valid for/: G; /Default/: false+ | Layer LayerRange -- ^ /Valid for/: EN; /Default/: \"\"+ | Layers LayerList -- ^ /Valid for/: G; /Default/: \"\"+ | LayerSep String -- ^ /Valid for/: G; /Default/: \" :\t\"+ | Layout String -- ^ /Valid for/: G; /Default/: \"\"+ | Len Double -- ^ /Valid for/: E; /Default/: 1.0(neato)/0.3(fdp); /Notes/: fdp, neato only+ | Levels Int -- ^ /Valid for/: G; /Default/: MAXINT; /Minimum/: 0.0; /Notes/: sfdp only+ | LevelsGap Double -- ^ /Valid for/: G; /Default/: 0.0; /Notes/: neato only+ | LHead String -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: dot only+ | LP Point -- ^ /Valid for/: EGC; /Notes/: write only+ | LTail String -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: dot only+ | Margin (Either Double Point) -- ^ /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 String -- ^ /Valid for/: G; /Default/: \"major\"; /Notes/: neato only+ | Model String -- ^ /Valid for/: G; /Default/: \"shortpath\"; /Notes/: neato only+ | Mosek Bool -- ^ /Valid for/: G; /Default/: false; /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+ | Normalize Bool -- ^ /Valid for/: G; /Default/: false; /Notes/: not dot+ | Nslimit Double -- ^ /Valid for/: G; /Notes/: dot only+ | Nslimit1 Double -- ^ /Valid for/: G; /Notes/: dot only+ | Ordering String -- ^ /Valid for/: G; /Default/: \"\"; /Notes/: dot only+ | Orientation Double -- ^ /Valid for/: N; /Default/: 0.0; /Minimum/: 360.0+ | OrientationGraph String -- ^ /Valid for/: G; /Default/: \"\"; /Notes/: Landscape if \"[lL]*\" and rotate not defined+ | OutputOrder OutputMode -- ^ /Valid for/: G; /Default/: breadthfirst+ | Overlap (Either String Bool) -- ^ /Valid for/: G; /Default/: true; /Notes/: not dot+ | OverlapScaling Double -- ^ /Valid for/: G; /Default/: -4; /Minimum/: -1.0e10; /Notes/: prism only+ | Pack (Either Bool Int) -- ^ /Valid for/: G; /Default/: false; /Notes/: not dot+ | PackMode PackMode -- ^ /Valid for/: G; /Default/: node; /Notes/: not dot+ | Pad (Either Double Point) -- ^ /Valid for/: G; /Default/: 0.0555 (4 points)+ | Page Point -- ^ /Valid for/: G+ | PageDir PageDir -- ^ /Valid for/: G; /Default/: BL+ | PenColor Color -- ^ /Valid for/: C; /Default/: 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; /Notes/: fdp, neato only+ | Pos (Either Point [Spline]) -- ^ /Valid for/: EN+ | QuadTree (Either QuadType Bool) -- ^ /Valid for/: G; /Default/: \"normal\"; /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/: TB; /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+ | ReMinCross Bool -- ^ /Valid for/: G; /Default/: false; /Notes/: dot only+ | RepulsiveForce Double -- ^ /Valid for/: G; /Default/: 1.0; /Minimum/: 0.0; /Notes/: sfdp only+ | Resolution Double -- ^ /Valid for/: G; /Default/: 96.0 | 0.0; /Notes/: svg, bitmap output only+ | Root (Either String Bool) -- ^ /Valid for/: GN; /Default/: \"\"(graphs) | false(nodes); /Notes/: circo, twopi only+ | Rotate Int -- ^ /Valid for/: G; /Default/: 0+ | SameHead String -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: dot only+ | SameTail String -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: dot only+ | SamplePoints Int -- ^ /Valid for/: N; /Default/: 8(output) | 20(overlap and image maps)+ | SearchSize Int -- ^ /Valid for/: G; /Default/: 30; /Notes/: dot only+ | Sep (Either Double Point) -- ^ /Valid for/: G; /Default/: +4; /Notes/: not dot+ | Shape Shape -- ^ /Valid for/: N; /Default/: ellipse+ | ShapeFile String -- ^ /Valid for/: N; /Default/: \"\"+ | ShowBoxes Int -- ^ /Valid for/: ENG; /Default/: 0; /Minimum/: 0; /Notes/: dot only+ | Sides Int -- ^ /Valid for/: N; /Default/: 4; /Minimum/: 0+ | Size Point -- ^ /Valid for/: G+ | Skew Double -- ^ /Valid for/: N; /Default/: 0.0; /Minimum/: -100.0+ | Smoothing SmoothType -- ^ /Valid for/: G; /Default/: \"none\"; /Notes/: sfdp only+ | SortV Int -- ^ /Valid for/: GCN; /Default/: 0; /Minimum/: 0+ | Splines (Either Bool String) -- ^ /Valid for/: G+ | Start StartType -- ^ /Valid for/: G; /Default/: \"\"; /Notes/: fdp, neato only+ | Style Style -- ^ /Valid for/: ENC+ | StyleSheet String -- ^ /Valid for/: G; /Default/: \"\"; /Notes/: svg only+ | TailURL URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | TailClip Bool -- ^ /Valid for/: E; /Default/: true+ | TailHref URL -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, map only+ | TailLabel (Either String URL) -- ^ /Valid for/: E; /Default/: \"\"+ | TailPort PortPos -- ^ /Valid for/: E; /Default/: center+ | TailTarget String -- ^ /Valid for/: E; /Default/: \<none\>; /Notes/: svg, map only+ | TailTooltip String -- ^ /Valid for/: E; /Default/: \"\"; /Notes/: svg, cmap only+ | Target String -- ^ /Valid for/: ENGC; /Default/: \<none\>; /Notes/: svg, map only+ | Tooltip String -- ^ /Valid for/: NEC; /Default/: \"\"; /Notes/: svg, cmap only+ | TrueColor Bool -- ^ /Valid for/: G; /Notes/: bitmap output only+ | Vertices [Point] -- ^ /Valid for/: N; /Notes/: write only+ | ViewPort ViewPort -- ^ /Valid for/: G; /Default/: \"\"+ | 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+ | Z Double -- ^ /Valid for/: N; /Default/: 0.0; /Minimum/: -MAXFLOAT | -1000+ deriving (Eq, Read)++instance Show Attribute where+ show (Damping v) = "Damping=" ++ show v+ show (K v) = "K=" ++ show v+ show (URL v) = "URL=" ++ show v+ show (ArrowHead v) = "arrowhead=" ++ show v+ show (ArrowSize v) = "arrowsize=" ++ show v+ show (ArrowTail v) = "arrowtail=" ++ show v+ show (Aspect v) = "aspect=" ++ show v+ show (Bb v) = "bb=" ++ show v+ show (BgColor v) = "bgcolor=" ++ show v+ show (Center v) = "center=" ++ show v+ show (Charset v) = "charset=" ++ v+ show (ClusterRank v) = "clusterrank=" ++ show v+ show (Color v) = "color=" ++ show v+ show (ColorScheme v) = "colorscheme=" ++ v+ show (Comment v) = "comment=" ++ v+ show (Compound v) = "compound=" ++ show v+ show (Concentrate v) = "concentrate=" ++ show v+ show (Constraint v) = "constraint=" ++ show v+ show (Decorate v) = "decorate=" ++ show v+ show (DefaultDist v) = "defaultdist=" ++ show v+ show (Dim v) = "dim=" ++ show v+ show (Dimen v) = "dimen=" ++ show v+ show (Dir v) = "dir=" ++ show v+ show (DirEdgeConstraints v) = "diredgeconstraints=" ++ show v+ show (Distortion v) = "distortion=" ++ show v+ show (DPI v) = "dpi=" ++ show v+ show (EdgeURL v) = "edgeURL=" ++ show v+ show (EdgeHref v) = "edgehref=" ++ show v+ show (EdgeTarget v) = "edgetarget=" ++ v+ show (EdgeTooltip v) = "edgetooltip=" ++ v+ show (Epsilon v) = "epsilon=" ++ show v+ show (ESep v) = "esep=" ++ show v+ show (FillColor v) = "fillcolor=" ++ show v+ show (FixedSize v) = "fixedsize=" ++ show v+ show (FontColor v) = "fontcolor=" ++ show v+ show (FontName v) = "fontname=" ++ v+ show (FontNames v) = "fontnames=" ++ v+ show (FontPath v) = "fontpath=" ++ v+ show (FontSize v) = "fontsize=" ++ show v+ show (Group v) = "group=" ++ v+ show (HeadURL v) = "headURL=" ++ show v+ show (HeadClip v) = "headclip=" ++ show v+ show (HeadHref v) = "headhref=" ++ show v+ show (HeadLabel v) = "headlabel=" ++ show v+ show (HeadPort v) = "headport=" ++ show v+ show (HeadTarget v) = "headtarget=" ++ show v+ show (HeadTooltip v) = "headtooltip=" ++ show v+ show (Height v) = "height=" ++ show v+ show (Href v) = "href=" ++ show v+ show (ID v) = "id=" ++ show v+ show (Image v) = "image=" ++ v+ show (ImageScale v) = "imagescale=" ++ show v+ show (Label v) = "label=" ++ show v+ show (LabelURL v) = "labelURL=" ++ show v+ show (LabelAngle v) = "labelangle=" ++ show v+ show (LabelDistance v) = "labeldistance=" ++ show v+ show (LabelFloat v) = "labelfloat=" ++ show v+ show (LabelFontColor v) = "labelfontcolor=" ++ show v+ show (LabelFontName v) = "labelfontname=" ++ v+ show (LabelFontSize v) = "labelfontsize=" ++ show v+ show (LabelHref v) = "labelhref=" ++ show v+ show (LabelJust v) = "labeljust=" ++ show v+ show (LabelLoc v) = "labelloc=" ++ show v+ show (LabelTarget v) = "labeltarget=" ++ v+ show (LabelTooltip v) = "labeltooltip=" ++ v+ show (Landscape v) = "landscape=" ++ show v+ show (Layer v) = "layer=" ++ show v+ show (Layers v) = "layers=" ++ show v+ show (LayerSep v) = "layersep=" ++ v+ show (Layout v) = "layout=" ++ v+ show (Len v) = "len=" ++ show v+ show (Levels v) = "levels=" ++ show v+ show (LevelsGap v) = "levelsgap=" ++ show v+ show (LHead v) = "lhead=" ++ v+ show (LP v) = "lp=" ++ show v+ show (LTail v) = "ltail=" ++ v+ show (Margin v) = "margin=" ++ show v+ show (MaxIter v) = "maxiter=" ++ show v+ show (MCLimit v) = "mclimit=" ++ show v+ show (MinDist v) = "mindist=" ++ show v+ show (MinLen v) = "minlen=" ++ show v+ show (Mode v) = "mode=" ++ v+ show (Model v) = "model=" ++ v+ show (Mosek v) = "mosek=" ++ show v+ show (NodeSep v) = "nodesep=" ++ show v+ show (NoJustify v) = "nojustify=" ++ show v+ show (Normalize v) = "normalize=" ++ show v+ show (Nslimit v) = "nslimit=" ++ show v+ show (Nslimit1 v) = "nslimit1=" ++ show v+ show (Ordering v) = "ordering=" ++ v+ show (Orientation v) = "orientation=" ++ show v+ show (OrientationGraph v) = "orientation=" ++ v+ show (OutputOrder v) = "outputorder=" ++ show v+ show (Overlap v) = "overlap=" ++ show v+ show (OverlapScaling v) = "overlap_scaling=" ++ show v+ show (Pack v) = "pack=" ++ show v+ show (PackMode v) = "packmode=" ++ show v+ show (Pad v) = "pad=" ++ show v+ show (Page v) = "page=" ++ show v+ show (PageDir v) = "pagedir=" ++ show v+ show (PenColor v) = "pencolor=" ++ show v+ show (PenWidth v) = "penwidth=" ++ show v+ show (Peripheries v) = "peripheries=" ++ show v+ show (Pin v) = "pin=" ++ show v+ show (Pos v) = "pos=" ++ show v+ show (QuadTree v) = "quadtree=" ++ show v+ show (Quantum v) = "quantum=" ++ show v+ show (Rank v) = "rank=" ++ show v+ show (RankDir v) = "rankdir=" ++ show v+ show (Ranksep v) = "ranksep=" ++ show v+ show (Ratio v) = "ratio=" ++ show v+ show (Rects v) = "rects=" ++ show v+ show (Regular v) = "regular=" ++ show v+ show (ReMinCross v) = "remincross=" ++ show v+ show (RepulsiveForce v) = "repulsiveforce=" ++ show v+ show (Resolution v) = "resolution=" ++ show v+ show (Root v) = "root=" ++ show v+ show (Rotate v) = "rotate=" ++ show v+ show (SameHead v) = "samehead=" ++ v+ show (SameTail v) = "sametail=" ++ v+ show (SamplePoints v) = "samplepoints=" ++ show v+ show (SearchSize v) = "searchsize=" ++ show v+ show (Sep v) = "sep=" ++ show v+ show (Shape v) = "shape=" ++ show v+ show (ShapeFile v) = "shapefile=" ++ v+ show (ShowBoxes v) = "showboxes=" ++ show v+ show (Sides v) = "sides=" ++ show v+ show (Size v) = "size=" ++ show v+ show (Skew v) = "skew=" ++ show v+ show (Smoothing v) = "smoothing=" ++ show v+ show (SortV v) = "sortv=" ++ show v+ show (Splines v) = "splines=" ++ show v+ show (Start v) = "start=" ++ show v+ show (Style v) = "style=" ++ show v+ show (StyleSheet v) = "stylesheet=" ++ v+ show (TailURL v) = "tailURL=" ++ show v+ show (TailClip v) = "tailclip=" ++ show v+ show (TailHref v) = "tailhref=" ++ show v+ show (TailLabel v) = "taillabel=" ++ show v+ show (TailPort v) = "tailport=" ++ show v+ show (TailTarget v) = "tailtarget=" ++ v+ show (TailTooltip v) = "tailtooltip=" ++ v+ show (Target v) = "target=" ++ v+ show (Tooltip v) = "tooltip=" ++ v+ show (TrueColor v) = "truecolor=" ++ show v+ show (Vertices v) = "vertices=" ++ show v+ show (ViewPort v) = "viewport=" ++ show v+ show (VoroMargin v) = "voro_margin=" ++ show v+ show (Weight v) = "weight=" ++ show v+ show (Width v) = "width=" ++ show v+ show (Z v) = "z=" ++ show v++instance Parseable Attribute where+ parse = oneOf [ liftM Damping $ parseField "Damping"+ , liftM K $ parseField "K"+ , liftM URL $ parseField "URL"+ , liftM ArrowHead $ parseField "arrowhead"+ , liftM ArrowSize $ parseField "arrowsize"+ , liftM ArrowTail $ parseField "arrowtail"+ , liftM Aspect $ parseField "aspect"+ , liftM Bb $ parseField "bb"+ , liftM BgColor $ parseField "bgcolor"+ , liftM Center $ parseBoolField "center"+ , liftM Charset $ parseField "charset"+ , liftM ClusterRank $ parseField "clusterrank"+ , liftM Color $ parseField "color"+ , liftM ColorScheme $ parseField "colorscheme"+ , liftM Comment $ parseField "comment"+ , liftM Compound $ parseBoolField "compound"+ , liftM Concentrate $ parseBoolField "concentrate"+ , liftM Constraint $ parseBoolField "constraint"+ , liftM Decorate $ parseBoolField "decorate"+ , liftM DefaultDist $ parseField "defaultdist"+ , liftM Dim $ parseField "dim"+ , liftM Dimen $ parseField "dimen"+ , liftM Dir $ parseField "dir"+ , liftM DirEdgeConstraints $ parseField "diredgeconstraints"+ , liftM Distortion $ parseField "distortion"+ , liftM DPI $ parseField "dpi"+ , liftM EdgeURL $ parseField "edgeURL"+ , liftM EdgeHref $ parseField "edgehref"+ , liftM EdgeTarget $ parseField "edgetarget"+ , liftM EdgeTooltip $ parseField "edgetooltip"+ , liftM Epsilon $ parseField "epsilon"+ , liftM ESep $ parseField "esep"+ , liftM FillColor $ parseField "fillcolor"+ , liftM FixedSize $ parseBoolField "fixedsize"+ , liftM FontColor $ parseField "fontcolor"+ , liftM FontName $ parseField "fontname"+ , liftM FontNames $ parseField "fontnames"+ , liftM FontPath $ parseField "fontpath"+ , liftM FontSize $ parseField "fontsize"+ , liftM Group $ parseField "group"+ , liftM HeadURL $ parseField "headURL"+ , liftM HeadClip $ parseBoolField "headclip"+ , liftM HeadHref $ parseField "headhref"+ , liftM HeadLabel $ parseField "headlabel"+ , liftM HeadPort $ parseField "headport"+ , liftM HeadTarget $ parseField "headtarget"+ , liftM HeadTooltip $ parseField "headtooltip"+ , liftM Height $ parseField "height"+ , liftM Href $ parseField "href"+ , liftM ID $ parseField "id"+ , liftM Image $ parseField "image"+ , liftM ImageScale $ parseField "imagescale"+ , liftM Label $ parseField "label"+ , liftM LabelURL $ parseField "labelURL"+ , liftM LabelAngle $ parseField "labelangle"+ , liftM LabelDistance $ parseField "labeldistance"+ , liftM LabelFloat $ parseBoolField "labelfloat"+ , liftM LabelFontColor $ parseField "labelfontcolor"+ , liftM LabelFontName $ parseField "labelfontname"+ , liftM LabelFontSize $ parseField "labelfontsize"+ , liftM LabelHref $ parseField "labelhref"+ , liftM LabelJust $ parseField "labeljust"+ , liftM LabelLoc $ parseField "labelloc"+ , liftM LabelTarget $ parseField "labeltarget"+ , liftM LabelTooltip $ parseField "labeltooltip"+ , liftM Landscape $ parseBoolField "landscape"+ , liftM Layer $ parseField "layer"+ , liftM Layers $ parseField "layers"+ , liftM LayerSep $ parseField "layersep"+ , liftM Layout $ parseField "layout"+ , liftM Len $ parseField "len"+ , liftM Levels $ parseField "levels"+ , liftM LevelsGap $ parseField "levelsgap"+ , liftM LHead $ parseField "lhead"+ , liftM LP $ parseField "lp"+ , liftM LTail $ parseField "ltail"+ , liftM Margin $ parseField "margin"+ , liftM MaxIter $ parseField "maxiter"+ , liftM MCLimit $ parseField "mclimit"+ , liftM MinDist $ parseField "mindist"+ , liftM MinLen $ parseField "minlen"+ , liftM Mode $ parseField "mode"+ , liftM Model $ parseField "model"+ , liftM Mosek $ parseBoolField "mosek"+ , liftM NodeSep $ parseField "nodesep"+ , liftM NoJustify $ parseBoolField "nojustify"+ , liftM Normalize $ parseBoolField "normalize"+ , liftM Nslimit $ parseField "nslimit"+ , liftM Nslimit1 $ parseField "nslimit1"+ , liftM Ordering $ parseField "ordering"+ , liftM Orientation $ parseField "orientation"+ , liftM OrientationGraph $ parseField "orientation"+ , liftM OutputOrder $ parseField "outputorder"+ , liftM Overlap $ parseField "overlap"+ , liftM OverlapScaling $ parseField "overlap_scaling"+ , liftM Pack $ parseField "pack"+ , liftM PackMode $ parseField "packmode"+ , liftM Pad $ parseField "pad"+ , liftM Page $ parseField "page"+ , liftM PageDir $ parseField "pagedir"+ , liftM PenColor $ parseField "pencolor"+ , liftM PenWidth $ parseField "penwidth"+ , liftM Peripheries $ parseField "peripheries"+ , liftM Pin $ parseBoolField "pin"+ , liftM Pos $ parseField "pos"+ , liftM QuadTree $ parseField "quadtree"+ , liftM Quantum $ parseField "quantum"+ , liftM Rank $ parseField "rank"+ , liftM RankDir $ parseField "rankdir"+ , liftM Ranksep $ parseField "ranksep"+ , liftM Ratio $ parseField "ratio"+ , liftM Rects $ parseField "rects"+ , liftM Regular $ parseBoolField "regular"+ , liftM ReMinCross $ parseBoolField "remincross"+ , liftM RepulsiveForce $ parseField "repulsiveforce"+ , liftM Resolution $ parseField "resolution"+ , liftM Root $ parseField "root"+ , liftM Rotate $ parseField "rotate"+ , liftM SameHead $ parseField "samehead"+ , liftM SameTail $ parseField "sametail"+ , liftM SamplePoints $ parseField "samplepoints"+ , liftM SearchSize $ parseField "searchsize"+ , liftM Sep $ parseField "sep"+ , liftM Shape $ parseField "shape"+ , liftM ShapeFile $ parseField "shapefile"+ , liftM ShowBoxes $ parseField "showboxes"+ , liftM Sides $ parseField "sides"+ , liftM Size $ parseField "size"+ , liftM Skew $ parseField "skew"+ , liftM Smoothing $ parseField "smoothing"+ , liftM SortV $ parseField "sortv"+ , liftM Splines $ parseField "splines"+ , liftM Start $ parseField "start"+ , liftM Style $ parseField "style"+ , liftM StyleSheet $ parseField "stylesheet"+ , liftM TailURL $ parseField "tailURL"+ , liftM TailClip $ parseBoolField "tailclip"+ , liftM TailHref $ parseField "tailhref"+ , liftM TailLabel $ parseField "taillabel"+ , liftM TailPort $ parseField "tailport"+ , liftM TailTarget $ parseField "tailtarget"+ , liftM TailTooltip $ parseField "tailtooltip"+ , liftM Target $ parseField "target"+ , liftM Tooltip $ parseField "tooltip"+ , liftM TrueColor $ parseBoolField "truecolor"+ , liftM Vertices $ parseField "vertices"+ , liftM ViewPort $ parseField "viewport"+ , liftM VoroMargin $ parseField "voro_margin"+ , liftM Weight $ parseField "weight"+ , liftM Width $ parseField "width"+ , liftM Z $ parseField "z"+ ]++-- | 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 Bb{} = True+usedByGraphs BgColor{} = True+usedByGraphs Center{} = True+usedByGraphs Charset{} = 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 ID{} = True+usedByGraphs Label{} = True+usedByGraphs LabelJust{} = True+usedByGraphs LabelLoc{} = True+usedByGraphs Landscape{} = True+usedByGraphs Layers{} = True+usedByGraphs LayerSep{} = True+usedByGraphs Layout{} = True+usedByGraphs Levels{} = True+usedByGraphs LevelsGap{} = True+usedByGraphs LP{} = 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 OrientationGraph{} = 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 Resolution{} = True+usedByGraphs Root{} = True+usedByGraphs Rotate{} = 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 _ = False++-- | Determine if this Attribute is valid for use with Clusters.+usedByClusters :: Attribute -> Bool+usedByClusters K{} = True+usedByClusters URL{} = True+usedByClusters BgColor{} = True+usedByClusters Color{} = True+usedByClusters ColorScheme{} = True+usedByClusters FillColor{} = True+usedByClusters FontColor{} = True+usedByClusters FontName{} = True+usedByClusters FontSize{} = True+usedByClusters Label{} = True+usedByClusters LabelJust{} = True+usedByClusters LabelLoc{} = True+usedByClusters LP{} = 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 _ = False++-- | Determine if this Attribute is valid for use with SubGraphs.+usedBySubGraphs :: Attribute -> Bool+usedBySubGraphs Rank{} = True+usedBySubGraphs _ = False++-- | Determine if this Attribute is valid for use with Nodes.+usedByNodes :: Attribute -> Bool+usedByNodes URL{} = 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 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 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 ShapeFile{} = 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 Z{} = 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 EdgeHref{} = True+usedByEdges EdgeTarget{} = True+usedByEdges EdgeTooltip{} = True+usedByEdges FontColor{} = True+usedByEdges FontName{} = True+usedByEdges FontSize{} = True+usedByEdges HeadURL{} = True+usedByEdges HeadClip{} = True+usedByEdges HeadHref{} = True+usedByEdges HeadLabel{} = True+usedByEdges HeadPort{} = True+usedByEdges HeadTarget{} = True+usedByEdges HeadTooltip{} = True+usedByEdges Href{} = 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 LabelHref{} = True+usedByEdges LabelTarget{} = True+usedByEdges LabelTooltip{} = True+usedByEdges Layer{} = True+usedByEdges Len{} = True+usedByEdges LHead{} = True+usedByEdges LP{} = 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 TailClip{} = True+usedByEdges TailHref{} = True+usedByEdges TailLabel{} = True+usedByEdges TailPort{} = True+usedByEdges TailTarget{} = True+usedByEdges TailTooltip{} = True+usedByEdges Target{} = True+usedByEdges Tooltip{} = True+usedByEdges Weight{} = True+usedByEdges _ = False++-- -----------------------------------------------------------------------------++newtype URL = UStr { urlString :: String }+ deriving (Eq, Read)++instance Show URL where+ show u = '<' : urlString u ++ ">"++instance Parseable URL where+ parse = do char open+ cnt <- many1 $ satisfy ((/=) close)+ char close+ return $ UStr cnt+ where+ open = '<'+ close = '>'++-- -----------------------------------------------------------------------------++data ArrowType = Normal | Inv+ | DotArrow | InvDot+ | ODot | InvODot+ | NoArrow | Tee+ | Empty | InvEmpty+ | Diamond | ODiamond+ | EDiamond | Crow+ | Box | OBox+ | Open | HalfOpen+ | Vee+ deriving (Eq, Read)++instance Show ArrowType where+ show Normal = "normal"+ show Inv = "inv"+ show DotArrow = "dot"+ show InvDot = "invdot"+ show ODot = "odot"+ show InvODot = "invodot"+ show NoArrow = "none"+ show Tee = "tee"+ show Empty = "empty"+ show InvEmpty = "invempty"+ show Diamond = "diamond"+ show ODiamond = "odiamond"+ show EDiamond = "ediamond"+ show Crow = "crow"+ show Box = "box"+ show OBox = "obox"+ show Open = "open"+ show HalfOpen = "halfopen"+ show Vee = "vee"++instance Parseable ArrowType where+ parse = optionalQuoted+ $ oneOf [ string "normal" >> return Normal+ , string "inv" >> return Inv+ , string "dot" >> return DotArrow+ , string "invdot" >> return InvDot+ , string "odot" >> return ODot+ , string "invodot" >> return InvODot+ , string "none" >> return NoArrow+ , string "tee" >> return Tee+ , string "empty" >> return Empty+ , string "invempty" >> return InvEmpty+ , string "diamond" >> return Diamond+ , string "odiamond" >> return ODiamond+ , string "ediamond" >> return EDiamond+ , string "crow" >> return Crow+ , string "box" >> return Box+ , string "obox" >> return OBox+ , string "open" >> return Open+ , string "halfopen" >> return HalfOpen+ , string "vee" >> return Vee+ ]++-- -----------------------------------------------------------------------------++data AspectType = RatioOnly Double+ | RatioPassCount Double Int+ deriving (Eq, Read)++instance Show AspectType where+ show (RatioOnly r) = show r+ show (RatioPassCount r p) = show $ show r ++ ',' : show p++instance Parseable AspectType where+ parse = oneOf [ liftM RatioOnly parse+ , quotedParse $ do r <- parse+ char ','+ whitespace'+ p <- parse+ return $ RatioPassCount r p+ ]++-- -----------------------------------------------------------------------------++data Rect = Rect Point Point+ deriving (Eq, Read)++instance Show Rect where+ show (Rect p1 p2) = show $ show p1 ++ ',' : show p2++instance Parseable Rect where+ parse = liftM (uncurry Rect) . quotedParse+ $ commaSep' parsePoint parsePoint++-- -----------------------------------------------------------------------------++data Color = RGB { red :: Word8+ , green :: Word8+ , blue :: Word8+ }+ | RGBA { red :: Word8+ , green :: Word8+ , blue :: Word8+ , alpha :: Word8+ }+ | HSV { hue :: Int+ , saturation :: Int+ , value :: Int+ }+ | ColorName String+ deriving (Eq, Read)++instance Show Color where+ show = show . showColor++ showList cs s = show $ go cs+ where+ go [] = s+ go [c] = showColor c ++ s+ go (c:cs') = showColor c ++ ':' : go cs'++showColor :: Color -> String+showColor (RGB r g b) = show $ '#' : foldr showWord8Pad "" [r,g,b]+showColor (RGBA r g b a) = show $ '#' : foldr showWord8Pad "" [r,g,b,a]+showColor (HSV h s v) = show $ show h ++ " " ++ show s ++ " " ++ show v+showColor (ColorName name) = name++showWord8Pad :: Word8 -> String -> String+showWord8Pad w s = padding ++ simple ++ s+ where+ simple = showHex w ""+ padding = replicate count '0'+ count = 2 - findCols 1 w+ findCols :: Int -> Word8 -> Int+ findCols c n+ | n < 16 = c+ | otherwise = findCols (c+1) (n `div` 16)++instance Parseable Color where+ parse = quotedParse parseColor++ parseList = quotedParse $ sepBy1 parseColor (char ':')++parseColor :: Parse Color+parseColor = oneOf [ parseHexBased+ , parseHSV+ , liftM ColorName parse -- Should we check it is a colour?+ ]+ where+ parseHexBased+ = do char '#'+ cs <- many1 parse2Hex+ return $ case cs of+ [r,g,b] -> RGB r g b+ [r,g,b,a] -> RGBA r g b a+ _ -> error $ "Not a valid hex Color specification: "+ ++ show cs+ parseHSV = do h <- parse+ parseSep+ s <- parse+ parseSep+ v <- parse+ return $ HSV h s v+ parseSep = oneOf [ string ","+ , whitespace+ ]+ parse2Hex = do c1 <- satisfy isHexDigit+ c2 <- satisfy isHexDigit+ let [(n, [])] = readHex [c1, c2]+ return n++-- -----------------------------------------------------------------------------++data ClusterMode = Local+ | Global+ | NoCluster+ deriving (Eq, Read)++instance Show ClusterMode where+ show Local = "local"+ show Global = "global"+ show NoCluster = "none"++instance Parseable ClusterMode where+ parse = optionalQuoted+ . oneOf+ $ [ string "local" >> return Local+ , string "global" >> return Global+ , string "none" >> return NoCluster+ ]++-- -----------------------------------------------------------------------------++data DirType = Forward | Back | Both | NoDir+ deriving (Eq, Read)++instance Show DirType where+ show Forward = "forward"+ show Back = "back"+ show Both = "both"+ show NoDir = "none"++instance Parseable DirType where+ parse = optionalQuoted+ $ oneOf [ string "forward" >> return Forward+ , string "back" >> return Back+ , string "both" >> return Both+ , string "none" >> return NoDir+ ]++-- -----------------------------------------------------------------------------++data Point = Point Int Int+ | PointD Double Double+ deriving (Eq, Read)++instance Show Point where+ show = show . showPoint++ showList ps s = unwords (map showPoint ps) ++ s++showPoint :: Point -> String+showPoint (Point x y) = show x ++ ',' : show y+showPoint (PointD x y) = show x ++ ',' : show y++instance Parseable Point where+ parse = quotedParse parsePoint++ parseList = quotedParse $ sepBy1 parsePoint whitespace++parsePoint :: Parse Point+parsePoint = oneOf [ liftM (uncurry Point) commaSep+ , liftM (uncurry PointD) commaSep+ ]++-- -----------------------------------------------------------------------------++data LayerRange = LRID LayerID+ | LRS LayerID String LayerID+ deriving (Eq, Read)++instance Show LayerRange where+ show (LRID lid) = show lid+ show (LRS id1 sep id2) = show $ show id1 ++ sep ++ show id2++instance Parseable LayerRange where+ parse = oneOf [ liftM LRID parse+ , do id1 <- parse+ sep <- parseLayerSep+ id2 <- parse+ return $ LRS id1 sep id2+ ]++parseLayerSep :: Parse String+parseLayerSep = many1 . oneOf+ $ map char defLayerSep++defLayerSep :: [Char]+defLayerSep = [' ', ':', '\t']++parseLayerName :: Parse String+parseLayerName = many1 $ satisfy (flip notElem defLayerSep)++data LayerID = AllLayers+ | LRInt Int+ | LRName String+ deriving (Eq, Read)++instance Show LayerID where+ show AllLayers = "all"+ show (LRInt n) = show n+ show (LRName nm) = nm++instance Parseable LayerID where+ parse = oneOf [ optionalQuotedString "all" >> return AllLayers+ , liftM LRInt $ optionalQuoted parse+ , liftM LRName parseLayerName+ ]++-- | The list represent (Separator, Name)+data LayerList = LL String [(String, String)]+ deriving (Eq, Read)++instance Show LayerList where+ show (LL l1 ols) = l1 ++ concatMap (uncurry (++)) ols++instance Parseable LayerList where+ parse = do l1 <- parseLayerName+ ols <- many $ do sep <- parseLayerSep+ lnm <- parseLayerName+ return (sep, lnm)+ return $ LL l1 ols++-- -----------------------------------------------------------------------------++data OutputMode = BreadthFirst | NodesFirst | EdgesFirst+ deriving (Eq, Read)++instance Show OutputMode where+ show BreadthFirst = "breadthfirst"+ show NodesFirst = "nodesfirst"+ show EdgesFirst = "edgesfirst"++instance Parseable OutputMode where+ parse = optionalQuoted+ $ oneOf [ string "breadthfirst" >> return BreadthFirst+ , string "nodesfirst" >> return NodesFirst+ , string "edgesfirst" >> return EdgesFirst+ ]++-- -----------------------------------------------------------------------------++data PackMode = PackNode+ | PackClust+ | PackGraph+ | PackArray Bool Bool (Maybe Int) -- ^ Sort by cols, sort+ -- by user, number of+ -- rows/cols+ deriving (Eq, Read)++instance Show PackMode where+ show PackNode = "node"+ show PackClust = "clust"+ show PackGraph = "graph"+ show (PackArray c u mi) = addNum . isU . isC . isUnder+ $ "array"+ where+ addNum = maybe id (flip (++) . show) mi+ isUnder = if c || u+ then flip (++) "_"+ else id+ isC = if c+ then flip (++) "c"+ else id+ isU = if u+ then flip (++) "u"+ else id++instance Parseable PackMode where+ parse = optionalQuoted+ $ oneOf [ string "node" >> return PackNode+ , string "clust" >> return PackClust+ , string "graph" >> return PackGraph+ , do string "array"+ mcu <- optional $ do char '_'+ many1 $ satisfy (not . isDigit)+ let c = hasChar mcu 'c'+ u = hasChar mcu 'u'+ mi <- optional parse+ return $ PackArray c u mi+ ]+ where+ hasChar ms c = maybe False (elem c) ms++-- -----------------------------------------------------------------------------++-- | 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, Read)++instance Show PageDir where+ show Bl = "BL"+ show Br = "BR"+ show Tl = "TL"+ show Tr = "TR"+ show Rb = "RB"+ show Rt = "RT"+ show Lb = "LB"+ show Lt = "LT"++instance Parseable PageDir where+ parse = optionalQuoted+ $ oneOf [ string "BL" >> return Bl+ , string "BR" >> return Br+ , string "TL" >> return Tl+ , string "TR" >> return Tr+ , string "RB" >> return Rb+ , string "RT" >> return Rt+ , string "LB" >> return Lb+ , string "LT" >> return Lt+ ]++-- -----------------------------------------------------------------------------++-- | The number of points in the list must be equivalent to 1 mod 3;+-- note that this is not checked.+data Spline = Spline (Maybe Point) (Maybe Point) [Point]+ deriving (Eq, Read)++instance Show Spline where+ show = show . showSpline++ showList ss o = show $ go ss+ where+ go [] = o+ go [s] = showSpline s ++ o+ go (s:ss') = showSpline s ++ ';' : go ss'++showSpline :: Spline -> String+showSpline (Spline ms me ps) = addS . addE+ . unwords+ $ map showPoint ps+ where+ addP t = maybe id (\p -> (++) $ t : ',' : show p)+ addS = addP 's' ms+ addE = addP 'e' me++instance Parseable Spline where+ parse = quotedParse parseSpline++ parseList = quotedParse $ sepBy1 parseSpline (char ';')++parseSpline :: Parse Spline+parseSpline = do ms <- parseP 's'+ whitespace+ me <- parseP 'e'+ whitespace+ ps <- sepBy1 parsePoint whitespace+ return $ Spline ms me ps+ where+ parseP t = optional $ do char t+ char ';'+ parse++-- -----------------------------------------------------------------------------++data QuadType = NormalQT+ | FastQT+ | NoQT+ deriving (Eq, Read)++instance Show QuadType where+ show NormalQT = "normal"+ show FastQT = "fast"+ show NoQT = "none"++instance Parseable QuadType where+ parse = optionalQuoted+ $ oneOf [ string "normal" >> return NormalQT+ , string "fast" >> return FastQT+ , string "none" >> return NoQT+ ]++-- -----------------------------------------------------------------------------++data RankType = SameRank+ | MinRank+ | SourceRank+ | MaxRank+ | SinkRank+ deriving (Eq, Read)++instance Show RankType where+ show SameRank = "same"+ show MinRank = "min"+ show SourceRank = "source"+ show MaxRank = "max"+ show SinkRank = "sink"++instance Parseable RankType where+ parse = optionalQuoted+ $ oneOf [ string "same" >> return SameRank+ , string "min" >> return MinRank+ , string "source" >> return SourceRank+ , string "max" >> return MaxRank+ , string "sink" >> return SinkRank+ ]++-- -----------------------------------------------------------------------------++data RankDir = FromTop+ | FromLeft+ | FromBottom+ | FromRight+ deriving (Eq, Read)++instance Show RankDir where+ show FromTop = "TB"+ show FromLeft = "LR"+ show FromBottom = "BT"+ show FromRight = "RL"++instance Parseable RankDir where+ parse = optionalQuoted+ $ oneOf [ string "TB" >> return FromTop+ , string "LR" >> return FromLeft+ , string "BT" >> return FromBottom+ , string "RL" >> return FromRight+ ]++-- -----------------------------------------------------------------------------++data Shape+ = BoxShape+ | Polygon+ | Ellipse+ | Circle+ | PointShape+ | Egg+ | Triangle+ | Plaintext+ | DiamondShape+ | Trapezium+ | Parallelogram+ | House+ | Pentagon+ | Hexagon+ | Septagon+ | Octagon+ | Doublecircle+ | Doubleoctagon+ | Tripleoctagon+ | Invtriangle+ | Invtrapezium+ | Invhouse+ | Mdiamond+ | Msquare+ | Mcircle+ | Rectangle+ | NoShape+ | Note+ | Tab+ | Folder+ | Box3d+ | Component+ deriving (Eq, Read)++instance Show Shape where+ show BoxShape = "box"+ show Polygon = "polygon"+ show Ellipse = "ellipse"+ show Circle = "circle"+ show PointShape = "point"+ show Egg = "egg"+ show Triangle = "triangle"+ show Plaintext = "plaintext"+ show DiamondShape = "diamond"+ show Trapezium = "trapezium"+ show Parallelogram = "parallelogram"+ show House = "house"+ show Pentagon = "pentagon"+ show Hexagon = "hexagon"+ show Septagon = "septagon"+ show Octagon = "octagon"+ show Doublecircle = "doublecircle"+ show Doubleoctagon = "doubleoctagon"+ show Tripleoctagon = "tripleoctagon"+ show Invtriangle = "invtriangle"+ show Invtrapezium = "invtrapezium"+ show Invhouse = "invhouse"+ show Mdiamond = "mdiamond"+ show Msquare = "msquare"+ show Mcircle = "mcircle"+ show Rectangle = "rectangle"+ show NoShape = "none"+ show Note = "note"+ show Tab = "tab"+ show Folder = "folder"+ show Box3d = "box3d"+ show Component = "component"++instance Parseable Shape where+ parse = optionalQuoted+ $ oneOf [ string "box" >> return BoxShape+ , string "polygon" >> return Polygon+ , string "ellipse" >> return Ellipse+ , string "circle" >> return Circle+ , string "point" >> return PointShape+ , string "egg" >> return Egg+ , string "triangle" >> return Triangle+ , string "plaintext" >> return Plaintext+ , string "diamond" >> return DiamondShape+ , string "trapezium" >> return Trapezium+ , string "parallelogram" >> return Parallelogram+ , string "house" >> return House+ , string "pentagon" >> return Pentagon+ , string "hexagon" >> return Hexagon+ , string "septagon" >> return Septagon+ , string "octagon" >> return Octagon+ , string "doublecircle" >> return Doublecircle+ , string "doubleoctagon" >> return Doubleoctagon+ , string "tripleoctagon" >> return Tripleoctagon+ , string "invtriangle" >> return Invtriangle+ , string "invtrapezium" >> return Invtrapezium+ , string "invhouse" >> return Invhouse+ , string "mdiamond" >> return Mdiamond+ , string "msquare" >> return Msquare+ , string "mcircle" >> return Mcircle+ , string "rectangle" >> return Rectangle+ , string "none" >> return NoShape+ , string "note" >> return Note+ , string "tab" >> return Tab+ , string "folder" >> return Folder+ , string "box3d" >> return Box3d+ , string "component" >> return Component+ ]++-- -----------------------------------------------------------------------------++data SmoothType = NoSmooth+ | AvgDist+ | GraphDist+ | PowerDist+ | RNG+ | Spring+ | TriangleSmooth+ deriving (Eq, Read)++instance Show SmoothType where+ show NoSmooth = "none"+ show AvgDist = "avg_dist"+ show GraphDist = "graph_dist"+ show PowerDist = "power_dist"+ show RNG = "rng"+ show Spring = "spring"+ show TriangleSmooth = "triangle"++instance Parseable SmoothType where+ parse = optionalQuoted+ $ oneOf [ string "none" >> return NoSmooth+ , string "avg_dist" >> return AvgDist+ , string "graph_dist" >> return GraphDist+ , string "power_dist" >> return PowerDist+ , string "rng" >> return RNG+ , string "spring" >> return Spring+ , string "triangle" >> return TriangleSmooth+ ]++-- -----------------------------------------------------------------------------++-- | It it assumed that at least one of these is @Just{}@.+data StartType = ST (Maybe STStyle) (Maybe Int) -- Use a Word?+ deriving (Eq, Read)++instance Show StartType where+ show (ST ms mi) = maybe id ((++) . show) ms+ $ maybe "" show mi++instance Parseable StartType where+ parse = optionalQuoted+ $ do ms <- optional parse+ mi <- optional parse+ return $ ST ms mi++data STStyle = RegularStyle+ | Self+ | Random+ deriving (Eq, Read)++instance Show STStyle where+ show RegularStyle = "regular"+ show Self = "self"+ show Random = "random"++instance Parseable STStyle where+ parse = oneOf [ string "regular" >> return RegularStyle+ , string "self" >> return Self+ , string "random" >> return Random+ ]++-- -----------------------------------------------------------------------------++data Style = Stl StyleName (Maybe String)+ deriving (Eq, Read)++instance Show Style where+ show (Stl nm marg) = maybe snm+ (\arg -> show $ snm ++ '(' : arg ++ ")")+ marg+ where+ snm = show nm++instance Parseable Style where+ parse = oneOf [ optionalQuoted $ liftM (\nm -> Stl nm Nothing) parse+ , quotedParse $ do nm <- parse+ char '('+ arg <- many1+ $ satisfy (flip notElem "()")++ char ')'+ return $ Stl nm (Just arg)+ ]++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+ | Diagonals -- ^ Nodes only+ | Rounded -- ^ Nodes and Clusters+ deriving (Eq, Read)++instance Show StyleName where+ show Filled = "filled"+ show Invisible = "invis"+ show Diagonals = "diagonals"+ show Rounded = "rounded"+ show Dashed = "dashed"+ show Dotted = "dotted"+ show Solid = "solid"+ show Bold = "bold"++instance Parseable StyleName where+ parse = optionalQuoted+ $ oneOf [ string "filled" >> return Filled+ , string "invis" >> return Invisible+ , string "diagonals" >> return Diagonals+ , string "rounded" >> return Rounded+ , string "dashed" >> return Dashed+ , string "dotted" >> return Dotted+ , string "solid" >> return Solid+ , string "bold" >> return Bold+ ]++-- -----------------------------------------------------------------------------++newtype PortPos = PP CompassPoint+ deriving (Eq, Read)++instance Show PortPos where+ show (PP cp) = show cp++instance Parseable PortPos where+ parse = liftM PP parse++data CompassPoint = North+ | NorthEast+ | East+ | SouthEast+ | South+ | SouthWest+ | West+ | NorthWest+ | CenterPoint+ | NoCP+ deriving (Eq, Read)++instance Show CompassPoint where+ show North = "n"+ show NorthEast = "ne"+ show East = "e"+ show SouthEast = "se"+ show South = "s"+ show SouthWest = "sw"+ show West = "w"+ show NorthWest = "nw"+ show CenterPoint = "c"+ show NoCP = "_"++instance Parseable CompassPoint where+ parse = optionalQuoted+ $ oneOf [ string "n" >> return North+ , string "ne" >> return NorthEast+ , string "e" >> return East+ , string "se" >> return SouthEast+ , string "s" >> return South+ , string "sw" >> return SouthWest+ , string "w" >> return West+ , string "nw" >> return NorthWest+ , string "c" >> return CenterPoint+ , string "_" >> return NoCP+ ]++-- -----------------------------------------------------------------------------++data ViewPort = VP { wVal :: Double+ , hVal :: Double+ , zVal :: Double+ , focus :: Maybe FocusType+ }+ deriving (Eq, Read)++instance Show ViewPort where+ show vp = show+ . maybe id (flip (++) . show) (focus vp)+ $ show (wVal vp)+ ++ ',' : show (hVal vp)+ ++ ',' : show (zVal vp)++instance Parseable ViewPort where+ parse = quotedParse+ $ do wv <- parse+ char ','+ hv <- parse+ char ','+ zv <- parse+ mf <- optional $ char ',' >> parse+ return $ VP wv hv zv mf++data FocusType = XY Point+ | NodeName String+ deriving (Eq, Read)++instance Show FocusType where+ show (XY p) = showPoint p+ show (NodeName nm) = nm++instance Parseable FocusType where+ parse = oneOf [ liftM XY parsePoint+ , liftM NodeName stringBlock+ ]++-- -----------------------------------------------------------------------------++-- | Note that 'VCenter' is only valid for Nodes.+data VerticalPlacement = VTop+ | VCenter+ | VBottom+ deriving (Eq, Read)++instance Show VerticalPlacement where+ show VTop = "t"+ show VCenter = "c"+ show VBottom = "b"++instance Parseable VerticalPlacement where+ parse = optionalQuoted+ $ oneOf [ string "t" >> return VTop+ , string "c" >> return VCenter+ , string "b" >> return VBottom+ ]+++-- -----------------------------------------------------------------------------++data ScaleType = UniformScale+ | NoScale+ | FillWidth+ | FillHeight+ | FillBoth+ deriving (Eq, Read)++instance Show ScaleType where+ show UniformScale = "true"+ show NoScale = "false"+ show FillWidth = "width"+ show FillHeight = "height"+ show FillBoth = "both"++instance Parseable ScaleType where+ parse = optionalQuoted+ $ oneOf [ string "true" >> return UniformScale+ , string "false" >> return NoScale+ , string "width" >> return FillWidth+ , string "height" >> return FillHeight+ , string "both" >> return FillBoth+ ]++-- -----------------------------------------------------------------------------++data Justification = JLeft+ | JRight+ | JCenter+ deriving (Eq, Read)++instance Show Justification where+ show JLeft = "l"+ show JRight = "r"+ show JCenter = "c"++instance Parseable Justification where+ parse = optionalQuoted+ $ oneOf [ string "l" >> return JLeft+ , string "r" >> return JRight+ , string "c" >> return JCenter+ ]++-- -----------------------------------------------------------------------------++data Ratios = AspectRatio Double+ | FillRatio+ | CompressRatio+ | ExpandRatio+ | AutoRatio+ deriving (Eq, Read)++instance Show Ratios where+ show (AspectRatio r) = show r+ show FillRatio = "fill"+ show CompressRatio = "compress"+ show ExpandRatio = "expand"+ show AutoRatio = "auto"++instance Parseable Ratios where+ parse = optionalQuoted+ $ oneOf [ liftM AspectRatio parse+ , string "fill" >> return FillRatio+ , string "compress" >> return CompressRatio+ , string "expand" >> return ExpandRatio+ , string "auto" >> return AutoRatio+ ]++-- -----------------------------------------------------------------------------++-- | Represents 'String's that definitely have quotes around them.+newtype QuotedString = QS { qStr :: String }+ deriving (Eq, Read)++instance Show QuotedString where+ show = show . qStr++instance Parseable QuotedString where+ parse = liftM (QS . tail . init) quotedString++-- -----------------------------------------------------------------------------
Data/GraphViz/Commands.hs view
@@ -30,15 +30,15 @@ import System.Process import Data.Array.IO import Control.Concurrent-import Control.Exception+import Control.Exception.Extensible import Data.GraphViz.Types -- | The available Graphviz commands.-data GraphvizCommand = DotCmd | Neato | TwoPi | Circo | Fdp+data GraphvizCommand = Dot | Neato | TwoPi | Circo | Fdp instance Show GraphvizCommand where- show DotCmd = "dot"+ show Dot = "dot" show Neato = "neato" show TwoPi = "twopi" show Circo = "circo"@@ -46,7 +46,7 @@ -- | The default command for directed graphs. dirCommand :: GraphvizCommand-dirCommand = DotCmd+dirCommand = Dot -- | The default command for undirected graphs. undirCommand :: GraphvizCommand@@ -62,7 +62,9 @@ -- Note that it is not possible to choose between output variants, -- and that not all of these may be available on your system. ----- This will probably be improved in future.+-- This will probably be improved in future. For now, more+-- information is available from:+-- <http://graphviz.org/doc/info/output.html> data GraphvizOutput = Canon | Cmap | Cmapx@@ -156,7 +158,8 @@ runGraphvizCommand :: GraphvizCommand -> DotGraph -> GraphvizOutput -> FilePath -> IO Bool runGraphvizCommand cmd gr t fp- = do pipe <- tryJust catcher $ openFile fp WriteMode+ = do pipe <- tryJust (\(SomeException _) -> return ())+ $ openFile fp WriteMode case pipe of (Left _) -> return False (Right f) -> do file <- graphvizWithHandle cmd gr t (flip squirt f)@@ -164,26 +167,23 @@ case file of (Just _) -> return True _ -> return False- where- catcher :: IOError -> Maybe ()- catcher _ = Just () -- graphvizWithHandle sometimes throws an error about handles not--- being closed properly: investigate.+-- being closed properly: investigate (now on the official TODO). -- | Run the chosen Graphviz command on this graph, but send the result to the -- given handle rather than to a file. -- The result is wrapped in 'Maybe' rather than throwing an error. graphvizWithHandle :: (Show a) => GraphvizCommand -> DotGraph -> GraphvizOutput- -> (Handle -> IO a) -> IO (Maybe a)+ -> (Handle -> IO a) -> IO (Maybe a) graphvizWithHandle cmd gr t f- = do (inp, outp, errp, proc) <- runInteractiveCommand command+ = do (inp, outp, errp, prc) <- runInteractiveCommand command forkIO $ hPrint inp gr >> hClose inp forkIO $ (hGetContents errp >>= hPutStr stderr >> hClose errp) a <- f outp -- Don't close outp until f finishes. a `seq` hClose outp- exitCode <- waitForProcess proc+ exitCode <- waitForProcess prc case exitCode of ExitSuccess -> return (Just a) _ -> return Nothing
Data/GraphViz/ParserCombinators.hs view
@@ -8,50 +8,231 @@ Maintainer : Ivan.Miljenovic@gmail.com This module defines simple helper functions for use with- @Text.ParserCombinators.Poly.Lazy@.+ "Text.ParserCombinators.Poly.Lazy".++ Note that the 'Parseable' instances for 'Bool', etc. match those+ specified for use with GraphViz (e.g. non-zero integers are+ equivalent to 'True').++ You should not be using this module; rather, it is here for+ informative/documentative reasons. If you want to parse a+ @'Data.GraphViz.Types.DotGraph'@, you should use+ @'Data.GraphViz.Types.parseDotGraph'@ rather than its 'Parseable'+ instance.+ -} -module Data.GraphViz.ParserCombinators where+module Data.GraphViz.ParserCombinators+ ( module Text.ParserCombinators.Poly.Lazy+ , Parse+ , Parseable(..)+ , stringBlock+ , quotedString+ , parseAndSpace+ , string+ , strings+ , hasString+ , char+ , whitespace+ , whitespace'+ , optionalQuotedString+ , optionalQuoted+ , quotedParse+ , newline+ , skipToNewline+ , parseField+ , parseBoolField+ , commaSep+ , commaSep'+ ) where import Text.ParserCombinators.Poly.Lazy+import Data.Char( digitToInt+ , isAsciiLower+ , isAsciiUpper+ , isDigit+ , isSpace+ , toLower+ )+import Data.Function(on)+import Data.Maybe(isJust)+import Data.Ratio((%)) import Control.Monad -string :: String -> Parser Char String+-- -----------------------------------------------------------------------------+-- Based off code from Text.Parse in the polyparse library++-- | A @ReadS@-like type alias.+type Parse a = Parser Char a++class Parseable a where+ parse :: Parse a++ parseList :: Parse [a]+ parseList = oneOf [ char '[' >> whitespace' >> char ']' >> return []+ , bracketSep (parseAndSpace $ char '[')+ (parseAndSpace $ char ',')+ (parseAndSpace $ char ']')+ (parseAndSpace parse)+ ]++instance Parseable Int where+ parse = parseInt++instance Parseable Double where+ parse = parseSigned parseFloat++instance Parseable Bool where+ parse = oneOf [ string "true" >> return True+ , string "false" >> return False+ , liftM (zero /=) parseInt+ ]+ where+ zero :: Int+ zero = 0++instance Parseable Char where+ parse = next++ parseList = oneOf [ stringBlock+ , quotedString+ ]++-- | Used when quotes are explicitly required;+-- note that the quotes are not stripped off.++instance (Parseable a) => Parseable [a] where+ parse = parseList++instance (Parseable a, Parseable b) => Parseable (Either a b) where+ parse = oneOf [ liftM Left parse+ , liftM Right parse+ ]++stringBlock :: Parse String+stringBlock = do frst <- satisfy frstCond+ rest <- many (satisfy restCond)+ return $ frst : rest+ where+ frstCond c = any ($c) [ isAsciiUpper+ , isAsciiLower+ , (==) '_'+ , \ x -> x >= '\200' && x <= '\377'+ ]+ restCond c = frstCond c || isDigit c++quotedString :: Parse String+quotedString = do w <- word+ if head w == '"'+ then return w+ else fail $ "Not a quoted string: " ++ w++word :: Parse String+word = P (\s-> case lex s of+ [] -> Failure s "no input? (impossible)"+ [("","")] -> Failure "" "no input?"+ [("",s')] -> Failure s' "lexing failed?"+ ((x,s'):_) -> Success s' x+ )++parseSigned :: Real a => Parse a -> Parse a+parseSigned p = do '-' <- next; commit (fmap negate p)+ `onFail`+ p++parseInt :: (Integral a) => Parse a+parseInt = do cs <- many1 (satisfy isDigit)+ return (foldl1 (\n d-> n*radix+d)+ (map (fromIntegral . digitToInt) cs))+ `adjustErr` (++ "\nexpected one or more digits")+ where+ radix = 10++parseFloat :: (RealFrac a) => Parse a+parseFloat = do ds <- many1 (satisfy isDigit)+ frac <- (do '.' <- next+ many (satisfy isDigit)+ `adjustErrBad` (++"expected digit after .")+ `onFail` return [] )+ expn <- parseExp `onFail` return 0+ ( return . fromRational . (* (10^^(expn - length frac)))+ . (%1) . fst+ . runParser parseInt) (ds++frac)+ `onFail`+ do w <- many (satisfy (not.isSpace))+ case map toLower w of+ "nan" -> return (0/0)+ "infinity" -> return (1/0)+ _ -> fail "expected a floating point number"+ where parseExp = do 'e' <- fmap toLower next+ commit (do '+' <- next; parseInt+ `onFail`+ parseSigned parseInt)++-- -----------------------------------------------------------------------------++parseAndSpace :: Parse a -> Parse a+parseAndSpace p = p `discard` whitespace'++string :: String -> Parse String string = mapM char -strings :: [String] -> Parser Char String+strings :: [String] -> Parse String strings = oneOf . map string -char :: Char -> Parser Char Char-char = satisfy . (==)+hasString :: String -> Parse Bool+hasString = liftM isJust . optional . string -noneOf :: (Eq a) => [a] -> Parser a a-noneOf t = satisfy (\x -> and . map ((/= x) $) $ t)+char :: Char -> Parse Char+char c = satisfy (((==) `on` toLower) c)+ `adjustErr`+ (++ "\nnot the expected char: " ++ [c]) -digit :: Parser Char Char-digit = oneOf . map char $ ['0'..'9']+noneOf :: (Eq a) => [a] -> Parser a a+noneOf t = satisfy (\x -> all (/= x) t) -number :: (Num a, Read a) => Parser Char a-number = liftM read $ many1 digit+whitespace :: Parse String+whitespace = many1 (satisfy isSpace) -floatingNumber :: (Floating a, Read a) => Parser Char a-floatingNumber = do { a::Integer <- number- ; char '.'- ; b::Integer <- number- ; return . read $ (show a) ++ ('.':(show b))- }+whitespace' :: Parse String+whitespace' = many (satisfy isSpace) -whitespace :: Parser Char String-whitespace = many1 (oneOf . map char $ [' ', '\t'])+optionalQuotedString :: String -> Parse String+optionalQuotedString = optionalQuoted . string -optionalQuotedString :: String -> Parser Char String-optionalQuotedString s = oneOf [string s, char '"' >> string s >>= \s' -> char '"' >> return s']+optionalQuoted :: Parse a -> Parse a+optionalQuoted p = oneOf [ p+ , quotedParse p+ ] -optionalQuoted :: Parser Char a -> Parser Char a-optionalQuoted p = oneOf [p, char '"' >> p >>= \r -> char '"' >> return r]+quotedParse :: Parse a -> Parse a+quotedParse p = char '"' >> p `discard` char '"' -newline :: Parser Char String+newline :: Parse String newline = oneOf . map string $ ["\r\n", "\n", "\r"] -skipToNewline :: Parser Char ()+skipToNewline :: Parse () skipToNewline = many (noneOf ['\n','\r']) >> newline >> return ()++parseField :: (Parseable a) => String -> Parse a+parseField fld = do string fld+ whitespace'+ char '='+ whitespace'+ parse++parseBoolField :: String -> Parse Bool+parseBoolField fld = oneOf [ parseField fld+ , string fld >> return True+ ]++commaSep :: (Parseable a, Parseable b) => Parse (a, b)+commaSep = commaSep' parse parse++commaSep' :: Parse a -> Parse b -> Parse (a,b)+commaSep' pa pb = do a <- pa+ whitespace'+ char ','+ whitespace'+ b <- pb+ return (a,b)
Data/GraphViz/Types.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE NamedFieldPuns- , ScopedTypeVariables- #-}- {- | Module : Data.GraphViz.Types Description : Definition of the GraphViz types.@@ -10,41 +6,81 @@ Maintainer : Ivan.Miljenovic@gmail.com This module defines the overall types and methods that interact- with them for the GraphViz library.+ with them for the GraphViz library. The specifications are based+ loosely upon the information available at:+ <http://graphviz.org/doc/info/lang.html> -} module Data.GraphViz.Types ( DotGraph(..)+ , GraphID(..) , DotNode(..) , DotEdge(..)- , readDotGraph+ , parseDotGraph+ , setID+ , makeStrict+ , isValidGraph+ , invalidAttributes ) where -import Data.Maybe-import Control.Monad-import Text.ParserCombinators.Poly.Lazy- import Data.GraphViz.Attributes import Data.GraphViz.ParserCombinators +import Data.Maybe+import Control.Monad+ -- ----------------------------------------------------------------------------- -- | The internal representation of a graph in Dot form.-data DotGraph = DotGraph { graphAttributes :: [Attribute]- , graphNodes :: [DotNode]- , graphEdges :: [DotEdge]- , directedGraph :: Bool+data DotGraph = DotGraph { strictGraph :: Bool+ , directedGraph :: Bool+ , graphID :: Maybe GraphID+ , graphAttributes :: [Attribute]+ , graphNodes :: [DotNode]+ , graphEdges :: [DotEdge] }+ deriving (Eq, Read) +-- | A strict graph disallows multiple edges.+makeStrict :: DotGraph -> DotGraph+makeStrict g = g { strictGraph = True }++setID :: GraphID -> DotGraph -> DotGraph+setID i g = g { graphID = Just i }++-- | Check if all the @Attribute@s are being used correctly.+isValidGraph :: DotGraph -> Bool+isValidGraph g = null gas && null nas && null eas+ where+ (gas, nas, eas) = invalidAttributes g++-- | Return all those @Attribute@s which aren't being used properly.+invalidAttributes :: DotGraph -> ( [Attribute]+ , [(DotNode, Attribute)]+ , [(DotEdge, Attribute)]+ )+invalidAttributes g = ( invalidGraphAttributes g+ , concatMap invalidNodeAttributes $ graphNodes g+ , concatMap invalidEdgeAttributes $ graphEdges g+ )++invalidGraphAttributes :: DotGraph -> [Attribute]+invalidGraphAttributes = filter (not . usedByGraphs) . graphAttributes+ instance Show DotGraph where- show (DotGraph { graphAttributes, graphNodes, graphEdges, directedGraph })- = unlines $ gType : " {" : (rest ++ ["}"])+ show g+ = unlines $ (hdr ++ " {") : (rest ++ ["}"]) where- gType = if directedGraph then dirGraph else undirGraph- rest = case graphAttributes of+ hdr = strct . addId $ gType+ strct = if strictGraph g+ then ("strict " ++)+ else id+ addId = maybe id (\ i -> flip (++) $ ' ' : show i) $ graphID g+ gType = if directedGraph g then dirGraph else undirGraph+ rest = case graphAttributes g of [] -> nodesEdges- a -> ("\tgraph " ++ (show a) ++ ";") : nodesEdges- nodesEdges = (map show graphNodes) ++ (map show graphEdges)+ a -> ("\tgraph " ++ show a ++ ";") : nodesEdges+ nodesEdges = map show (graphNodes g) ++ map show (graphEdges g) dirGraph :: String dirGraph = "digraph"@@ -52,10 +88,69 @@ undirGraph :: String undirGraph = "graph" +-- | Parse a limited subset of the Dot language to form a 'DotGraph'+-- (that is, the caveats listed in "Data.GraphViz.Attributes" aside,+-- Dot graphs are parsed if they match the layout of DotGraph).+parseDotGraph :: Parse DotGraph+parseDotGraph = parse++instance Parseable DotGraph where+ parse = do isStrict <- parseAndSpace $ hasString "strict"+ gType <- strings [dirGraph,undirGraph]+ gId <- optional (parse `discard` whitespace)+ whitespace+ char '{'+ skipToNewline+ as <- liftM concat $+ many (whitespace' >>+ oneOf [ string "edge" >> skipToNewline >> return []+ , string "node" >> skipToNewline >> return []+ , string "graph" >> whitespace+ >> parse `discard` skipToNewline+ ]+ )+ ns <- many1 (whitespace' >> parse `discard` skipToNewline)+ es <- many1 (whitespace' >> parse `discard` skipToNewline)+ char '}'+ return DotGraph { strictGraph = isStrict+ , directedGraph = gType == dirGraph+ , graphID = gId+ , graphAttributes = as+ , graphNodes = ns+ , graphEdges = es+ }++ `adjustErr`+ (++ "\nNot a valid DotGraph")+ -- ----------------------------------------------------------------------------- +data GraphID = Str String+ | Num Double+ | QStr QuotedString+ | HTML URL+ deriving (Eq, Read)++instance Show GraphID where+ show (Str str) = str+ show (Num n) = show n+ show (QStr str) = show str+ show (HTML url) = show url++instance Parseable GraphID where+ parse = oneOf [ liftM Str stringBlock+ , liftM Num parse+ , liftM QStr parse+ , liftM HTML parse+ ]+ `adjustErr`+ (++ "\nNot a valid GraphID")++-- -----------------------------------------------------------------------------+ -- | A node in 'DotGraph' is either a singular node, or a cluster -- containing nodes (or more clusters) within it.+-- At the moment, clusters are not parsed. data DotNode = DotNode { nodeID :: Int , nodeAttributes :: [Attribute]@@ -64,24 +159,46 @@ , clusterAttributes :: [Attribute] , clusterElems :: [DotNode] }+ deriving (Eq, Read) +invalidNodeAttributes :: DotNode -> [(DotNode, Attribute)]+invalidNodeAttributes n@DotNode{} = map ((,) n)+ . filter (not . usedByNodes)+ $ nodeAttributes n+invalidNodeAttributes c@DotCluster{} = cErr ++ nErr+ where+ cErr = map ((,) c) . filter (not . usedByClusters)+ $ clusterAttributes c+ nErr = concatMap invalidNodeAttributes $ clusterElems c+ instance Show DotNode where- show n = init . unlines . addTabs $ nodesToString n+ show = init . unlines . addTabs . nodesToString nodesToString :: DotNode -> [String]-nodesToString (DotNode { nodeID, nodeAttributes })- | null nodeAttributes = [nID ++ ";"]- | otherwise = [nID ++ (' ':((show nodeAttributes) ++ ";"))]+nodesToString n@(DotNode {})+ | null nAs = [nID ++ ";"]+ | otherwise = [nID ++ (' ':(show nAs ++ ";"))] where- nID = show nodeID-nodesToString (DotCluster { clusterID, clusterAttributes, clusterElems })- = ["subgraph cluster_" ++ clusterID ++ " {"] ++ (addTabs inner) ++ ["}"]+ nID = show $ nodeID n+ nAs = nodeAttributes n+nodesToString c@(DotCluster {})+ = ["subgraph cluster_" ++ clusterID c ++ " {"] ++ addTabs inner ++ ["}"] where- inner = case clusterAttributes of+ inner = case clusterAttributes c of [] -> nodes- a -> ("graph " ++ (show a) ++ ";") : nodes- nodes = concatMap nodesToString clusterElems+ a -> ("graph " ++ show a ++ ";") : nodes+ nodes = concatMap nodesToString $ clusterElems c ++instance Parseable DotNode where+ parse = do nId <- parse+ as <- optional (whitespace >> parse)+ char ';'+ return DotNode { nodeID = nId+ , nodeAttributes = fromMaybe [] as }+ `adjustErr`+ (++ "\nNot a valid DotNode")+ -- | Prefix each 'String' with a tab character. addTabs :: [String] -> [String] addTabs = map ('\t':)@@ -94,15 +211,22 @@ , edgeAttributes :: [Attribute] , directedEdge :: Bool }+ deriving (Eq, Read) +invalidEdgeAttributes :: DotEdge -> [(DotEdge, Attribute)]+invalidEdgeAttributes e = map ((,) e)+ . filter (not . usedByEdges)+ $ edgeAttributes e+ instance Show DotEdge where- show (DotEdge { edgeHeadNodeID, edgeTailNodeID, edgeAttributes, directedEdge })- = '\t' : ((show edgeTailNodeID) ++ edge ++ (show edgeHeadNodeID) ++ attributes)+ show e+ = '\t' : (show (edgeHeadNodeID e)+ ++ edge ++ show (edgeTailNodeID e) ++ attributes) where- edge = " " ++ (if directedEdge then dirEdge else undirEdge) ++ " "- attributes = case edgeAttributes of+ edge = " " ++ (if directedEdge e then dirEdge else undirEdge) ++ " "+ attributes = case edgeAttributes e of [] -> ";"- a -> ' ':((show a) ++ ";")+ a -> ' ':(show a ++ ";") dirEdge :: String dirEdge = "->"@@ -110,52 +234,21 @@ undirEdge :: String undirEdge = "--" --- --------------------------------------------------------------------------------- | Parse a 'DotNode'-readDotNode :: Parser Char DotNode-readDotNode = do { optional whitespace- ; nodeID <- number- ; as <- optional (whitespace >> readAttributesList)- ; char ';'- ; skipToNewline- ; return (DotNode { nodeID, nodeAttributes = fromMaybe [] as })- }---- | Parse a 'DotEdge'-readDotEdge :: Parser Char DotEdge-readDotEdge = do { optional whitespace- ; edgeTailNodeID <- number- ; whitespace- ; edge <- strings [dirEdge,undirEdge]- ; whitespace- ; edgeHeadNodeID <- number- ; as <- optional (whitespace >> readAttributesList)- ; char ';'- ; skipToNewline- ; return (DotEdge { edgeHeadNodeID- , edgeTailNodeID- , edgeAttributes = fromMaybe [] as- , directedEdge = edge == dirEdge })- }+instance Parseable DotEdge where+ parse = do whitespace'+ eHead <- parse+ whitespace+ edgeType <- strings [dirEdge,undirEdge]+ whitespace+ eTail <- parse+ as <- optional (whitespace >> parse)+ char ';'+ return DotEdge { edgeHeadNodeID = eHead+ , edgeTailNodeID = eTail+ , edgeAttributes = fromMaybe [] as+ , directedEdge = edgeType == dirEdge+ }+ `adjustErr`+ (++ "\nNot a valid DotEdge") --- | Parse a 'DotGraph'-readDotGraph :: Parser Char DotGraph-readDotGraph = do { d <- strings [dirGraph,undirGraph]- ; let directedGraph = d == dirGraph- ; whitespace- ; char '{'- ; skipToNewline- ; graphAttributes- <- liftM concat $- many (optional whitespace >>- oneOf [ (string "edge" >> skipToNewline >> return [])- , (string "node" >> skipToNewline >> return [])- , (string "graph" >> whitespace >> readAttributesList >>= \as -> skipToNewline >> return as)- ]- )- ; graphNodes <- many readDotNode- ; graphEdges <- many readDotEdge- ; char '}'- ; return $ DotGraph { graphAttributes, graphNodes, graphEdges, directedGraph }- }+-- -----------------------------------------------------------------------------
TODO view
@@ -1,10 +1,16 @@ Areas to work on: -* Add support for Data.Graph-style graphs.+* Utilise the generic graph class once it is finalised. * Allow user to choose whether or not the graph is meant to be directed or undirected. -* Ensure Data.GraphViz.Attributes contains all supported attributes for Dot.+* Improve parsing to fully (or at least follow more closely) support Dot. -* Remove (or at least minimise) usage of extensions.+* Improve clustering/subgraph support.++* Use a PrettyPrinter rather than Show to generate Dot output.++* Improve Output support.++* Find and fix the handle closing bug with graphvizWithHandle.
graphviz.cabal view
@@ -1,37 +1,47 @@ Name: graphviz-Version: 2009.5.1+Version: 2999.0.0.0 Stability: Beta-Copyright: Matthew Sackman, Ivan Lazar Miljenovic-Category: Graphics-Maintainer: Ivan.Miljenovic@gmail.com-Author: Matthew Sackman, Ivan Lazar Miljenovic+Synopsis: GraphViz wrapper for Haskell.+Description: Provides convenient functions to convert FGL+ graphs into the Dot language used by the+ GraphViz <http://graphviz.org/> programs with a+ large degree of customisation for layout, etc.++ Also allows a limited amount of parsing of Dot,+ and usage of GraphViz to attach positional data+ to each node and edge in the graph.+Category: Graphs, Graphics License: BSD3 License-File: LICENSE-Extra-Source-Files: TODO-Cabal-Version: >= 1.6+Copyright: Matthew Sackman, Ivan Lazar Miljenovic+Author: Matthew Sackman, Ivan Lazar Miljenovic+Maintainer: Ivan.Miljenovic@gmail.com Build-Type: Simple-Synopsis: GraphViz wrapper for Haskell.-Description:- Provides convenient functions to convert FGL graphs into the Dot- language used by the GraphViz (http://graphviz.org/) programs with a- large degree of customisation for layout, etc.+Cabal-Version: >= 1.6+Extra-Source-Files: TODO+ Changelog - Also allows a limited amount of parsing of Dot, and usage of- GraphViz to attach positional data to each node and edge in the- graph.+Source-Repository head+ Type: darcs+ Location: http://code.haskell.org/graphviz Library {- Build-Depends: base == 4.*, containers, process, array,- fgl, polyparse >= 1.1+ Build-Depends: base >= 3 && < 5,+ extensible-exceptions,+ containers,+ process,+ array,+ fgl,+ polyparse >= 1.1 Exposed-Modules: Data.GraphViz Data.GraphViz.Types Data.GraphViz.Commands Data.GraphViz.Attributes+ Data.GraphViz.ParserCombinators Other-Modules: Data.GraphViz.Types.Clustering- Data.GraphViz.ParserCombinators - Ghc-Options: -Wall -fno-warn-name-shadowing+ Ghc-Options: -Wall Ghc-Prof-Options: -prof -auto-all }