graphviz 2999.6.0.0 → 2999.7.0.0
raw patch · 20 files changed
+5352/−620 lines, 20 filesdep +QuickCheckdep +bytestringdep +colourdep −arraydep −parallelnew-component:exe:graphviz-testsuitePVP ok
version bump matches the API change (PVP)
Dependencies added: QuickCheck, bytestring, colour, filepath
Dependencies removed: array, parallel
API changes (from Hackage documentation)
- Data.GraphViz.Attributes: ColorName :: String -> Color
- Data.GraphViz.Attributes: HSV :: Double -> Double -> Double -> Color
- Data.GraphViz.Attributes: OrientationGraph :: String -> Attribute
- Data.GraphViz.Attributes: RGB :: Word8 -> Word8 -> Word8 -> Color
- Data.GraphViz.Attributes: RGBA :: Word8 -> Word8 -> Word8 -> Word8 -> Color
- Data.GraphViz.Attributes: Ranksep :: Double -> Attribute
- Data.GraphViz.Attributes: alpha :: Color -> Word8
- Data.GraphViz.Attributes: blue :: Color -> Word8
- Data.GraphViz.Attributes: data Color
- Data.GraphViz.Attributes: green :: Color -> Word8
- Data.GraphViz.Attributes: hue :: Color -> Double
- Data.GraphViz.Attributes: instance Eq Color
- Data.GraphViz.Attributes: instance ParseDot Color
- Data.GraphViz.Attributes: instance PrintDot Color
- Data.GraphViz.Attributes: instance Read Color
- Data.GraphViz.Attributes: instance Show Color
- Data.GraphViz.Attributes: red :: Color -> Word8
- Data.GraphViz.Attributes: saturation :: Color -> Double
- Data.GraphViz.Attributes: value :: Color -> Double
- Data.GraphViz.Commands: Cmap :: GraphvizOutput
- Data.GraphViz.Commands: Cmapx_np :: GraphvizOutput
- Data.GraphViz.Commands: Dia :: GraphvizOutput
- Data.GraphViz.Commands: Hpgl :: GraphvizOutput
- Data.GraphViz.Commands: Imap_np :: GraphvizOutput
- Data.GraphViz.Commands: Ismap :: GraphvizOutput
- Data.GraphViz.Commands: Jpe :: GraphvizOutput
- Data.GraphViz.Commands: Jpg :: GraphvizOutput
- Data.GraphViz.Commands: Mif :: GraphvizOutput
- Data.GraphViz.Commands: Mp :: GraphvizOutput
- Data.GraphViz.Commands: Pcl :: GraphvizOutput
- Data.GraphViz.Commands: Pic :: GraphvizOutput
- Data.GraphViz.Commands: Svgz :: GraphvizOutput
- Data.GraphViz.Commands: Tk :: GraphvizOutput
- Data.GraphViz.Commands: Vmlz :: GraphvizOutput
- Data.GraphViz.Commands: Vtx :: GraphvizOutput
- Data.GraphViz.Commands: Wbmp :: GraphvizOutput
- Data.GraphViz.Commands: Xdot :: GraphvizOutput
- Data.GraphViz.Types.Parsing: preprocess :: String -> String
+ Data.GraphViz: prettyPrint :: (PrintDot a) => DotGraph a -> IO String
+ Data.GraphViz: prettyPrint' :: (PrintDot a) => DotGraph a -> String
+ Data.GraphViz.Attributes: RankSep :: Double -> Attribute
+ Data.GraphViz.Attributes: defLayerSep :: [Char]
+ Data.GraphViz.Attributes: instance Bounded ArrowFill
+ Data.GraphViz.Attributes: instance Bounded ArrowShape
+ Data.GraphViz.Attributes: instance Bounded ArrowSide
+ Data.GraphViz.Attributes: instance Bounded ClusterMode
+ Data.GraphViz.Attributes: instance Bounded CompassPoint
+ Data.GraphViz.Attributes: instance Bounded DEConstraints
+ Data.GraphViz.Attributes: instance Bounded DirType
+ Data.GraphViz.Attributes: instance Bounded EdgeType
+ Data.GraphViz.Attributes: instance Bounded Justification
+ Data.GraphViz.Attributes: instance Bounded ModeType
+ Data.GraphViz.Attributes: instance Bounded Model
+ Data.GraphViz.Attributes: instance Bounded OutputMode
+ Data.GraphViz.Attributes: instance Bounded PageDir
+ Data.GraphViz.Attributes: instance Bounded QuadType
+ Data.GraphViz.Attributes: instance Bounded RankDir
+ Data.GraphViz.Attributes: instance Bounded RankType
+ Data.GraphViz.Attributes: instance Bounded STStyle
+ Data.GraphViz.Attributes: instance Bounded ScaleType
+ Data.GraphViz.Attributes: instance Bounded Shape
+ Data.GraphViz.Attributes: instance Bounded SmoothType
+ Data.GraphViz.Attributes: instance Bounded VerticalPlacement
+ Data.GraphViz.Attributes: instance Enum ArrowFill
+ Data.GraphViz.Attributes: instance Enum ArrowShape
+ Data.GraphViz.Attributes: instance Enum ArrowSide
+ Data.GraphViz.Attributes: instance Enum ClusterMode
+ Data.GraphViz.Attributes: instance Enum CompassPoint
+ Data.GraphViz.Attributes: instance Enum DEConstraints
+ Data.GraphViz.Attributes: instance Enum DirType
+ Data.GraphViz.Attributes: instance Enum EdgeType
+ Data.GraphViz.Attributes: instance Enum Justification
+ Data.GraphViz.Attributes: instance Enum ModeType
+ Data.GraphViz.Attributes: instance Enum Model
+ Data.GraphViz.Attributes: instance Enum OutputMode
+ Data.GraphViz.Attributes: instance Enum PageDir
+ Data.GraphViz.Attributes: instance Enum QuadType
+ Data.GraphViz.Attributes: instance Enum RankDir
+ Data.GraphViz.Attributes: instance Enum RankType
+ Data.GraphViz.Attributes: instance Enum STStyle
+ Data.GraphViz.Attributes: instance Enum ScaleType
+ Data.GraphViz.Attributes: instance Enum Shape
+ Data.GraphViz.Attributes: instance Enum SmoothType
+ Data.GraphViz.Attributes: instance Enum VerticalPlacement
+ Data.GraphViz.Attributes: instance Ord ArrowFill
+ Data.GraphViz.Attributes: instance Ord ArrowModifier
+ Data.GraphViz.Attributes: instance Ord ArrowShape
+ Data.GraphViz.Attributes: instance Ord ArrowSide
+ Data.GraphViz.Attributes: instance Ord ArrowType
+ Data.GraphViz.Attributes: instance Ord AspectType
+ Data.GraphViz.Attributes: instance Ord Attribute
+ Data.GraphViz.Attributes: instance Ord ClusterMode
+ Data.GraphViz.Attributes: instance Ord CompassPoint
+ Data.GraphViz.Attributes: instance Ord DEConstraints
+ Data.GraphViz.Attributes: instance Ord DPoint
+ Data.GraphViz.Attributes: instance Ord DirType
+ Data.GraphViz.Attributes: instance Ord EdgeType
+ Data.GraphViz.Attributes: instance Ord FocusType
+ Data.GraphViz.Attributes: instance Ord Justification
+ Data.GraphViz.Attributes: instance Ord Label
+ Data.GraphViz.Attributes: instance Ord LayerID
+ Data.GraphViz.Attributes: instance Ord LayerList
+ Data.GraphViz.Attributes: instance Ord LayerRange
+ Data.GraphViz.Attributes: instance Ord ModeType
+ Data.GraphViz.Attributes: instance Ord Model
+ Data.GraphViz.Attributes: instance Ord OutputMode
+ Data.GraphViz.Attributes: instance Ord Overlap
+ Data.GraphViz.Attributes: instance Ord Pack
+ Data.GraphViz.Attributes: instance Ord PackMode
+ Data.GraphViz.Attributes: instance Ord PageDir
+ Data.GraphViz.Attributes: instance Ord Point
+ Data.GraphViz.Attributes: instance Ord PortPos
+ Data.GraphViz.Attributes: instance Ord Pos
+ Data.GraphViz.Attributes: instance Ord QuadType
+ Data.GraphViz.Attributes: instance Ord RankDir
+ Data.GraphViz.Attributes: instance Ord RankType
+ Data.GraphViz.Attributes: instance Ord Ratios
+ Data.GraphViz.Attributes: instance Ord Rect
+ Data.GraphViz.Attributes: instance Ord Root
+ Data.GraphViz.Attributes: instance Ord STStyle
+ Data.GraphViz.Attributes: instance Ord ScaleType
+ Data.GraphViz.Attributes: instance Ord Shape
+ Data.GraphViz.Attributes: instance Ord SmoothType
+ Data.GraphViz.Attributes: instance Ord Spline
+ Data.GraphViz.Attributes: instance Ord StartType
+ Data.GraphViz.Attributes: instance Ord StyleItem
+ Data.GraphViz.Attributes: instance Ord StyleName
+ Data.GraphViz.Attributes: instance Ord URL
+ Data.GraphViz.Attributes: instance Ord VerticalPlacement
+ Data.GraphViz.Attributes: instance Ord ViewPort
+ Data.GraphViz.Attributes: notLayerSep :: Char -> Bool
+ Data.GraphViz.Attributes.Colors: Accent :: BrewerName
+ Data.GraphViz.Attributes.Colors: AliceBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: AntiqueWhite :: X11Color
+ Data.GraphViz.Attributes.Colors: AntiqueWhite1 :: X11Color
+ Data.GraphViz.Attributes.Colors: AntiqueWhite2 :: X11Color
+ Data.GraphViz.Attributes.Colors: AntiqueWhite3 :: X11Color
+ Data.GraphViz.Attributes.Colors: AntiqueWhite4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Aquamarine :: X11Color
+ Data.GraphViz.Attributes.Colors: Aquamarine1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Aquamarine2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Aquamarine3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Aquamarine4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Azure :: X11Color
+ Data.GraphViz.Attributes.Colors: Azure1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Azure2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Azure3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Azure4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Beige :: X11Color
+ Data.GraphViz.Attributes.Colors: Bisque :: X11Color
+ Data.GraphViz.Attributes.Colors: Bisque1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Bisque2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Bisque3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Bisque4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Black :: X11Color
+ Data.GraphViz.Attributes.Colors: BlanchedAlmond :: X11Color
+ Data.GraphViz.Attributes.Colors: Blue :: X11Color
+ Data.GraphViz.Attributes.Colors: Blue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Blue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Blue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Blue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: BlueViolet :: X11Color
+ Data.GraphViz.Attributes.Colors: Blues :: BrewerName
+ Data.GraphViz.Attributes.Colors: Brbg :: BrewerName
+ Data.GraphViz.Attributes.Colors: BrewerColor :: Word8 -> Color
+ Data.GraphViz.Attributes.Colors: BrewerScheme :: BrewerName -> Word8 -> ColorScheme
+ Data.GraphViz.Attributes.Colors: Brown :: X11Color
+ Data.GraphViz.Attributes.Colors: Brown1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Brown2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Brown3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Brown4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Bugn :: BrewerName
+ Data.GraphViz.Attributes.Colors: Bupu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Burlywood :: X11Color
+ Data.GraphViz.Attributes.Colors: Burlywood1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Burlywood2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Burlywood3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Burlywood4 :: X11Color
+ Data.GraphViz.Attributes.Colors: CadetBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: CadetBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: CadetBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: CadetBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: CadetBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chartreuse :: X11Color
+ Data.GraphViz.Attributes.Colors: Chartreuse1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chartreuse2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chartreuse3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chartreuse4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chocolate :: X11Color
+ Data.GraphViz.Attributes.Colors: Chocolate1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chocolate2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chocolate3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Chocolate4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Coral :: X11Color
+ Data.GraphViz.Attributes.Colors: Coral1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Coral2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Coral3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Coral4 :: X11Color
+ Data.GraphViz.Attributes.Colors: CornFlowerBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: CornSilk :: X11Color
+ Data.GraphViz.Attributes.Colors: CornSilk1 :: X11Color
+ Data.GraphViz.Attributes.Colors: CornSilk2 :: X11Color
+ Data.GraphViz.Attributes.Colors: CornSilk3 :: X11Color
+ Data.GraphViz.Attributes.Colors: CornSilk4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Crimson :: X11Color
+ Data.GraphViz.Attributes.Colors: Cyan :: X11Color
+ Data.GraphViz.Attributes.Colors: Cyan1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Cyan2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Cyan3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Cyan4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Dark2 :: BrewerName
+ Data.GraphViz.Attributes.Colors: DarkGoldenrod :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkGoldenrod1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkGoldenrod2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkGoldenrod3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkGoldenrod4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOliveGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOliveGreen1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOliveGreen2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOliveGreen3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOliveGreen4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrange :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrange1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrange2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrange3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrange4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrchid :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrchid1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrchid2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrchid3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkOrchid4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSalmon :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSeaGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSeaGreen1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSeaGreen2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSeaGreen3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSeaGreen4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSlateBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSlateGray :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSlateGray1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSlateGray2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSlateGray3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkSlateGray4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkTurquoise :: X11Color
+ Data.GraphViz.Attributes.Colors: DarkViolet :: X11Color
+ Data.GraphViz.Attributes.Colors: Darkkhaki :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepPink :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepPink1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepPink2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepPink3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepPink4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepSkyBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepSkyBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepSkyBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepSkyBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DeepSkyBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: DimGray :: X11Color
+ Data.GraphViz.Attributes.Colors: DodgerBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: DodgerBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: DodgerBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: DodgerBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: DodgerBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Firebrick :: X11Color
+ Data.GraphViz.Attributes.Colors: Firebrick1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Firebrick2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Firebrick3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Firebrick4 :: X11Color
+ Data.GraphViz.Attributes.Colors: FloralWhite :: X11Color
+ Data.GraphViz.Attributes.Colors: ForestGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: Gainsboro :: X11Color
+ Data.GraphViz.Attributes.Colors: GhostWhite :: X11Color
+ Data.GraphViz.Attributes.Colors: Gnbu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Gold :: X11Color
+ Data.GraphViz.Attributes.Colors: Gold1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gold2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gold3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gold4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Goldenrod :: X11Color
+ Data.GraphViz.Attributes.Colors: Goldenrod1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Goldenrod2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Goldenrod3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Goldenrod4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray0 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray10 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray100 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray11 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray12 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray13 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray14 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray15 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray16 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray17 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray18 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray19 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray20 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray21 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray22 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray23 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray24 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray25 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray26 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray27 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray28 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray29 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray30 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray31 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray32 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray33 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray34 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray35 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray36 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray37 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray38 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray39 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray40 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray41 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray42 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray43 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray44 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray45 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray46 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray47 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray48 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray49 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray5 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray50 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray51 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray52 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray53 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray54 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray55 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray56 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray57 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray58 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray59 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray6 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray60 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray61 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray62 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray63 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray64 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray65 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray66 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray67 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray68 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray69 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray7 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray70 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray71 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray72 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray73 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray74 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray75 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray76 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray77 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray78 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray79 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray8 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray80 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray81 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray82 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray83 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray84 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray85 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray86 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray87 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray88 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray89 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray9 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray90 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray91 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray92 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray93 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray94 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray95 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray96 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray97 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray98 :: X11Color
+ Data.GraphViz.Attributes.Colors: Gray99 :: X11Color
+ Data.GraphViz.Attributes.Colors: Green :: X11Color
+ Data.GraphViz.Attributes.Colors: Green1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Green2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Green3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Green4 :: X11Color
+ Data.GraphViz.Attributes.Colors: GreenYellow :: X11Color
+ Data.GraphViz.Attributes.Colors: Greens :: BrewerName
+ Data.GraphViz.Attributes.Colors: Greys :: BrewerName
+ Data.GraphViz.Attributes.Colors: HSV :: Double -> Double -> Double -> Color
+ Data.GraphViz.Attributes.Colors: HoneyDew :: X11Color
+ Data.GraphViz.Attributes.Colors: HoneyDew1 :: X11Color
+ Data.GraphViz.Attributes.Colors: HoneyDew2 :: X11Color
+ Data.GraphViz.Attributes.Colors: HoneyDew3 :: X11Color
+ Data.GraphViz.Attributes.Colors: HoneyDew4 :: X11Color
+ Data.GraphViz.Attributes.Colors: HotPink :: X11Color
+ Data.GraphViz.Attributes.Colors: HotPink1 :: X11Color
+ Data.GraphViz.Attributes.Colors: HotPink2 :: X11Color
+ Data.GraphViz.Attributes.Colors: HotPink3 :: X11Color
+ Data.GraphViz.Attributes.Colors: HotPink4 :: X11Color
+ Data.GraphViz.Attributes.Colors: IndianRed :: X11Color
+ Data.GraphViz.Attributes.Colors: IndianRed1 :: X11Color
+ Data.GraphViz.Attributes.Colors: IndianRed2 :: X11Color
+ Data.GraphViz.Attributes.Colors: IndianRed3 :: X11Color
+ Data.GraphViz.Attributes.Colors: IndianRed4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Indigo :: X11Color
+ Data.GraphViz.Attributes.Colors: Ivory :: X11Color
+ Data.GraphViz.Attributes.Colors: Ivory1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Ivory2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Ivory3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Ivory4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Khaki :: X11Color
+ Data.GraphViz.Attributes.Colors: Khaki1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Khaki2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Khaki3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Khaki4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Lavender :: X11Color
+ Data.GraphViz.Attributes.Colors: LavenderBlush :: X11Color
+ Data.GraphViz.Attributes.Colors: LavenderBlush1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LavenderBlush2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LavenderBlush3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LavenderBlush4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LawnGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: LemonChiffon :: X11Color
+ Data.GraphViz.Attributes.Colors: LemonChiffon1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LemonChiffon2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LemonChiffon3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LemonChiffon4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: LightBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightCoral :: X11Color
+ Data.GraphViz.Attributes.Colors: LightCyan :: X11Color
+ Data.GraphViz.Attributes.Colors: LightCyan1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightCyan2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightCyan3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightCyan4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGoldenrod :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGoldenrod1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGoldenrod2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGoldenrod3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGoldenrod4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGoldenrodYellow :: X11Color
+ Data.GraphViz.Attributes.Colors: LightGray :: X11Color
+ Data.GraphViz.Attributes.Colors: LightPink :: X11Color
+ Data.GraphViz.Attributes.Colors: LightPink1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightPink2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightPink3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightPink4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSalmon :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSalmon1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSalmon2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSalmon3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSalmon4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSeaGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSkyBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSkyBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSkyBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSkyBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSkyBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSlateBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSlateGray :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSteelBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSteelBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSteelBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSteelBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightSteelBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightYellow :: X11Color
+ Data.GraphViz.Attributes.Colors: LightYellow1 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightYellow2 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightYellow3 :: X11Color
+ Data.GraphViz.Attributes.Colors: LightYellow4 :: X11Color
+ Data.GraphViz.Attributes.Colors: LimeGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: Linen :: X11Color
+ Data.GraphViz.Attributes.Colors: Magenta :: X11Color
+ Data.GraphViz.Attributes.Colors: Magenta1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Magenta2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Magenta3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Magenta4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Maroon :: X11Color
+ Data.GraphViz.Attributes.Colors: Maroon1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Maroon2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Maroon3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Maroon4 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumAquamarine :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumOrchid :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumOrchid1 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumOrchid2 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumOrchid3 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumOrchid4 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumPurple :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumPurple1 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumPurple2 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumPurple3 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumPurple4 :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumSeaGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumSlateBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumSpringGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumTurquoise :: X11Color
+ Data.GraphViz.Attributes.Colors: MediumVioletRed :: X11Color
+ Data.GraphViz.Attributes.Colors: MidnightBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: MintCream :: X11Color
+ Data.GraphViz.Attributes.Colors: MistyRose :: X11Color
+ Data.GraphViz.Attributes.Colors: MistyRose1 :: X11Color
+ Data.GraphViz.Attributes.Colors: MistyRose2 :: X11Color
+ Data.GraphViz.Attributes.Colors: MistyRose3 :: X11Color
+ Data.GraphViz.Attributes.Colors: MistyRose4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Moccasin :: X11Color
+ Data.GraphViz.Attributes.Colors: NavajoWhite :: X11Color
+ Data.GraphViz.Attributes.Colors: NavajoWhite1 :: X11Color
+ Data.GraphViz.Attributes.Colors: NavajoWhite2 :: X11Color
+ Data.GraphViz.Attributes.Colors: NavajoWhite3 :: X11Color
+ Data.GraphViz.Attributes.Colors: NavajoWhite4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Navy :: X11Color
+ Data.GraphViz.Attributes.Colors: NavyBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: OldLace :: X11Color
+ Data.GraphViz.Attributes.Colors: OliveDrab :: X11Color
+ Data.GraphViz.Attributes.Colors: OliveDrab1 :: X11Color
+ Data.GraphViz.Attributes.Colors: OliveDrab2 :: X11Color
+ Data.GraphViz.Attributes.Colors: OliveDrab3 :: X11Color
+ Data.GraphViz.Attributes.Colors: OliveDrab4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orange :: X11Color
+ Data.GraphViz.Attributes.Colors: Orange1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orange2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orange3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orange4 :: X11Color
+ Data.GraphViz.Attributes.Colors: OrangeRed :: X11Color
+ Data.GraphViz.Attributes.Colors: OrangeRed1 :: X11Color
+ Data.GraphViz.Attributes.Colors: OrangeRed2 :: X11Color
+ Data.GraphViz.Attributes.Colors: OrangeRed3 :: X11Color
+ Data.GraphViz.Attributes.Colors: OrangeRed4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Oranges :: BrewerName
+ Data.GraphViz.Attributes.Colors: Orchid :: X11Color
+ Data.GraphViz.Attributes.Colors: Orchid1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orchid2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orchid3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orchid4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Orrd :: BrewerName
+ Data.GraphViz.Attributes.Colors: Paired :: BrewerName
+ Data.GraphViz.Attributes.Colors: PaleGoldenrod :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleGreen1 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleGreen2 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleGreen3 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleGreen4 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleTurquoise :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleTurquoise1 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleTurquoise2 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleTurquoise3 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleTurquoise4 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleVioletRed :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleVioletRed1 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleVioletRed2 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleVioletRed3 :: X11Color
+ Data.GraphViz.Attributes.Colors: PaleVioletRed4 :: X11Color
+ Data.GraphViz.Attributes.Colors: PapayaWhip :: X11Color
+ Data.GraphViz.Attributes.Colors: Pastel1 :: BrewerName
+ Data.GraphViz.Attributes.Colors: Pastel2 :: BrewerName
+ Data.GraphViz.Attributes.Colors: PeachPuff :: X11Color
+ Data.GraphViz.Attributes.Colors: PeachPuff1 :: X11Color
+ Data.GraphViz.Attributes.Colors: PeachPuff2 :: X11Color
+ Data.GraphViz.Attributes.Colors: PeachPuff3 :: X11Color
+ Data.GraphViz.Attributes.Colors: PeachPuff4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Peru :: X11Color
+ Data.GraphViz.Attributes.Colors: Pink :: X11Color
+ Data.GraphViz.Attributes.Colors: Pink1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Pink2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Pink3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Pink4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Piyg :: BrewerName
+ Data.GraphViz.Attributes.Colors: Plum :: X11Color
+ Data.GraphViz.Attributes.Colors: Plum1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Plum2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Plum3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Plum4 :: X11Color
+ Data.GraphViz.Attributes.Colors: PowderBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: Prgn :: BrewerName
+ Data.GraphViz.Attributes.Colors: Pubu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Pubugn :: BrewerName
+ Data.GraphViz.Attributes.Colors: Puor :: BrewerName
+ Data.GraphViz.Attributes.Colors: Purd :: BrewerName
+ Data.GraphViz.Attributes.Colors: Purple :: X11Color
+ Data.GraphViz.Attributes.Colors: Purple1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Purple2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Purple3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Purple4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Purples :: BrewerName
+ Data.GraphViz.Attributes.Colors: RGB :: Word8 -> Word8 -> Word8 -> Color
+ Data.GraphViz.Attributes.Colors: RGBA :: Word8 -> Word8 -> Word8 -> Word8 -> Color
+ Data.GraphViz.Attributes.Colors: Rdbu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Rdgy :: BrewerName
+ Data.GraphViz.Attributes.Colors: Rdpu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Rdylbu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Rdylgn :: BrewerName
+ Data.GraphViz.Attributes.Colors: Red :: X11Color
+ Data.GraphViz.Attributes.Colors: Red1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Red2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Red3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Red4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Reds :: BrewerName
+ Data.GraphViz.Attributes.Colors: RosyBrown :: X11Color
+ Data.GraphViz.Attributes.Colors: RosyBrown1 :: X11Color
+ Data.GraphViz.Attributes.Colors: RosyBrown2 :: X11Color
+ Data.GraphViz.Attributes.Colors: RosyBrown3 :: X11Color
+ Data.GraphViz.Attributes.Colors: RosyBrown4 :: X11Color
+ Data.GraphViz.Attributes.Colors: RoyalBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: RoyalBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: RoyalBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: RoyalBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: RoyalBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SaddleBrown :: X11Color
+ Data.GraphViz.Attributes.Colors: Salmon :: X11Color
+ Data.GraphViz.Attributes.Colors: Salmon1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Salmon2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Salmon3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Salmon4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SandyBrown :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaGreen1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaGreen2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaGreen3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaGreen4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaShell :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaShell1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaShell2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaShell3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SeaShell4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Set1 :: BrewerName
+ Data.GraphViz.Attributes.Colors: Set2 :: BrewerName
+ Data.GraphViz.Attributes.Colors: Set3 :: BrewerName
+ Data.GraphViz.Attributes.Colors: Sienna :: X11Color
+ Data.GraphViz.Attributes.Colors: Sienna1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Sienna2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Sienna3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Sienna4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SkyBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: SkyBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SkyBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SkyBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SkyBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateGray :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateGray1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateGray2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateGray3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SlateGray4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Snow :: X11Color
+ Data.GraphViz.Attributes.Colors: Snow1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Snow2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Snow3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Snow4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Spectral :: BrewerName
+ Data.GraphViz.Attributes.Colors: SpringGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: SpringGreen1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SpringGreen2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SpringGreen3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SpringGreen4 :: X11Color
+ Data.GraphViz.Attributes.Colors: SteelBlue :: X11Color
+ Data.GraphViz.Attributes.Colors: SteelBlue1 :: X11Color
+ Data.GraphViz.Attributes.Colors: SteelBlue2 :: X11Color
+ Data.GraphViz.Attributes.Colors: SteelBlue3 :: X11Color
+ Data.GraphViz.Attributes.Colors: SteelBlue4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tan :: X11Color
+ Data.GraphViz.Attributes.Colors: Tan1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tan2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tan3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tan4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Thistle :: X11Color
+ Data.GraphViz.Attributes.Colors: Thistle1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Thistle2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Thistle3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Thistle4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tomato :: X11Color
+ Data.GraphViz.Attributes.Colors: Tomato1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tomato2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tomato3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Tomato4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Transparent :: X11Color
+ Data.GraphViz.Attributes.Colors: Turquoise :: X11Color
+ Data.GraphViz.Attributes.Colors: Turquoise1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Turquoise2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Turquoise3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Turquoise4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Violet :: X11Color
+ Data.GraphViz.Attributes.Colors: VioletRed :: X11Color
+ Data.GraphViz.Attributes.Colors: VioletRed1 :: X11Color
+ Data.GraphViz.Attributes.Colors: VioletRed2 :: X11Color
+ Data.GraphViz.Attributes.Colors: VioletRed3 :: X11Color
+ Data.GraphViz.Attributes.Colors: VioletRed4 :: X11Color
+ Data.GraphViz.Attributes.Colors: Wheat :: X11Color
+ Data.GraphViz.Attributes.Colors: Wheat1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Wheat2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Wheat3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Wheat4 :: X11Color
+ Data.GraphViz.Attributes.Colors: White :: X11Color
+ Data.GraphViz.Attributes.Colors: WhiteSmoke :: X11Color
+ Data.GraphViz.Attributes.Colors: X11 :: ColorScheme
+ Data.GraphViz.Attributes.Colors: X11Color :: X11Color -> Color
+ Data.GraphViz.Attributes.Colors: Yellow :: X11Color
+ Data.GraphViz.Attributes.Colors: Yellow1 :: X11Color
+ Data.GraphViz.Attributes.Colors: Yellow2 :: X11Color
+ Data.GraphViz.Attributes.Colors: Yellow3 :: X11Color
+ Data.GraphViz.Attributes.Colors: Yellow4 :: X11Color
+ Data.GraphViz.Attributes.Colors: YellowGreen :: X11Color
+ Data.GraphViz.Attributes.Colors: Ylgn :: BrewerName
+ Data.GraphViz.Attributes.Colors: Ylgnbu :: BrewerName
+ Data.GraphViz.Attributes.Colors: Ylorbr :: BrewerName
+ Data.GraphViz.Attributes.Colors: Ylorrd :: BrewerName
+ Data.GraphViz.Attributes.Colors: alpha :: Color -> Word8
+ Data.GraphViz.Attributes.Colors: blue :: Color -> Word8
+ Data.GraphViz.Attributes.Colors: data BrewerName
+ Data.GraphViz.Attributes.Colors: data Color
+ Data.GraphViz.Attributes.Colors: data ColorScheme
+ Data.GraphViz.Attributes.Colors: data X11Color
+ Data.GraphViz.Attributes.Colors: fromAColour :: AlphaColour Double -> Color
+ Data.GraphViz.Attributes.Colors: fromColour :: Colour Double -> Color
+ Data.GraphViz.Attributes.Colors: green :: Color -> Word8
+ Data.GraphViz.Attributes.Colors: hue :: Color -> Double
+ Data.GraphViz.Attributes.Colors: instance Bounded BrewerName
+ Data.GraphViz.Attributes.Colors: instance Bounded X11Color
+ Data.GraphViz.Attributes.Colors: instance Enum BrewerName
+ Data.GraphViz.Attributes.Colors: instance Enum X11Color
+ Data.GraphViz.Attributes.Colors: instance Eq BrewerName
+ Data.GraphViz.Attributes.Colors: instance Eq Color
+ Data.GraphViz.Attributes.Colors: instance Eq ColorScheme
+ Data.GraphViz.Attributes.Colors: instance Eq X11Color
+ Data.GraphViz.Attributes.Colors: instance Ord BrewerName
+ Data.GraphViz.Attributes.Colors: instance Ord Color
+ Data.GraphViz.Attributes.Colors: instance Ord ColorScheme
+ Data.GraphViz.Attributes.Colors: instance Ord X11Color
+ Data.GraphViz.Attributes.Colors: instance ParseDot BrewerName
+ Data.GraphViz.Attributes.Colors: instance ParseDot Color
+ Data.GraphViz.Attributes.Colors: instance ParseDot ColorScheme
+ Data.GraphViz.Attributes.Colors: instance ParseDot X11Color
+ Data.GraphViz.Attributes.Colors: instance PrintDot BrewerName
+ Data.GraphViz.Attributes.Colors: instance PrintDot Color
+ Data.GraphViz.Attributes.Colors: instance PrintDot ColorScheme
+ Data.GraphViz.Attributes.Colors: instance PrintDot X11Color
+ Data.GraphViz.Attributes.Colors: instance Read BrewerName
+ Data.GraphViz.Attributes.Colors: instance Read Color
+ Data.GraphViz.Attributes.Colors: instance Read ColorScheme
+ Data.GraphViz.Attributes.Colors: instance Read X11Color
+ Data.GraphViz.Attributes.Colors: instance Show BrewerName
+ Data.GraphViz.Attributes.Colors: instance Show Color
+ Data.GraphViz.Attributes.Colors: instance Show ColorScheme
+ Data.GraphViz.Attributes.Colors: instance Show X11Color
+ Data.GraphViz.Attributes.Colors: red :: Color -> Word8
+ Data.GraphViz.Attributes.Colors: saturation :: Color -> Double
+ Data.GraphViz.Attributes.Colors: toColour :: Color -> Maybe (AlphaColour Double)
+ Data.GraphViz.Attributes.Colors: value :: Color -> Double
+ Data.GraphViz.Attributes.Colors: x11Colour :: X11Color -> AlphaColour Double
+ Data.GraphViz.Commands: Bmp :: GraphvizOutput
+ Data.GraphViz.Commands: CmapxNP :: GraphvizOutput
+ Data.GraphViz.Commands: Error :: String -> RunResult
+ Data.GraphViz.Commands: Ico :: GraphvizOutput
+ Data.GraphViz.Commands: ImapNP :: GraphvizOutput
+ Data.GraphViz.Commands: Success :: RunResult
+ Data.GraphViz.Commands: SvgZ :: GraphvizOutput
+ Data.GraphViz.Commands: Tiff :: GraphvizOutput
+ Data.GraphViz.Commands: VmlZ :: GraphvizOutput
+ Data.GraphViz.Commands: WBmp :: GraphvizOutput
+ Data.GraphViz.Commands: XDot :: GraphvizOutput
+ Data.GraphViz.Commands: addExtension :: (GraphvizOutput -> FilePath -> IO a) -> GraphvizOutput -> FilePath -> IO a
+ Data.GraphViz.Commands: data GraphvizCanvas
+ Data.GraphViz.Commands: data RunResult
+ Data.GraphViz.Commands: hGetContents' :: Handle -> IO String
+ Data.GraphViz.Commands: instance Eq GraphvizCanvas
+ Data.GraphViz.Commands: instance Eq GraphvizCommand
+ Data.GraphViz.Commands: instance Eq GraphvizOutput
+ Data.GraphViz.Commands: instance Eq RunResult
+ Data.GraphViz.Commands: instance GraphvizResult GraphvizCanvas
+ Data.GraphViz.Commands: instance GraphvizResult GraphvizOutput
+ Data.GraphViz.Commands: instance Ord GraphvizCanvas
+ Data.GraphViz.Commands: instance Ord GraphvizCommand
+ Data.GraphViz.Commands: instance Ord GraphvizOutput
+ Data.GraphViz.Commands: instance Ord RunResult
+ Data.GraphViz.Commands: instance Read GraphvizCanvas
+ Data.GraphViz.Commands: instance Read GraphvizCommand
+ Data.GraphViz.Commands: instance Read GraphvizOutput
+ Data.GraphViz.Commands: instance Read RunResult
+ Data.GraphViz.Commands: instance Show GraphvizCanvas
+ Data.GraphViz.Commands: instance Show RunResult
+ Data.GraphViz.Commands: runGraphvizCanvas :: (PrintDot n) => GraphvizCommand -> DotGraph n -> GraphvizCanvas -> IO RunResult
+ Data.GraphViz.Commands: runGraphvizCanvas' :: (PrintDot n) => DotGraph n -> GraphvizCanvas -> IO RunResult
+ Data.GraphViz.Types: instance (Ord a) => Ord (DotEdge a)
+ Data.GraphViz.Types: instance (Ord a) => Ord (DotError a)
+ Data.GraphViz.Types: instance (Ord a) => Ord (DotGraph a)
+ Data.GraphViz.Types: instance (Ord a) => Ord (DotNode a)
+ Data.GraphViz.Types: instance (Ord a) => Ord (DotStatements a)
+ Data.GraphViz.Types: instance (Ord a) => Ord (DotSubGraph a)
+ Data.GraphViz.Types: instance Ord GlobalAttributes
+ Data.GraphViz.Types: instance Ord GraphID
+ Data.GraphViz.Types.Parsing: instance ParseDot Word8
+ Data.GraphViz.Types.Parsing: isIntString :: String -> Bool
+ Data.GraphViz.Types.Parsing: isNumString :: String -> Bool
+ Data.GraphViz.Types.Parsing: onlyBool :: Parse Bool
+ Data.GraphViz.Types.Parsing: orQuote :: Parse Char -> Parse Char
+ Data.GraphViz.Types.Parsing: parseIt :: (ParseDot a) => String -> (a, String)
+ Data.GraphViz.Types.Parsing: preProcess :: String -> String
+ Data.GraphViz.Types.Parsing: quoteChar :: Char
+ Data.GraphViz.Types.Printing: addQuotes :: String -> DotCode -> DotCode
+ Data.GraphViz.Types.Printing: instance PrintDot Word8
+ Data.GraphViz.Types.Printing: printIt :: (PrintDot a) => a -> String
- Data.GraphViz.Attributes: ColorScheme :: String -> Attribute
+ Data.GraphViz.Attributes: ColorScheme :: ColorScheme -> Attribute
- Data.GraphViz.Commands: Gtk :: GraphvizOutput
+ Data.GraphViz.Commands: Gtk :: GraphvizCanvas
- Data.GraphViz.Commands: Xlib :: GraphvizOutput
+ Data.GraphViz.Commands: Xlib :: GraphvizCanvas
- Data.GraphViz.Commands: graphvizWithHandle :: (PrintDot n, Show a) => GraphvizCommand -> DotGraph n -> GraphvizOutput -> (Handle -> IO a) -> IO (Maybe a)
+ Data.GraphViz.Commands: graphvizWithHandle :: (PrintDot n, Show a) => GraphvizCommand -> DotGraph n -> GraphvizOutput -> (Handle -> IO a) -> IO (Either String a)
- Data.GraphViz.Commands: runGraphviz :: (PrintDot n) => DotGraph n -> GraphvizOutput -> FilePath -> IO Bool
+ Data.GraphViz.Commands: runGraphviz :: (PrintDot n) => DotGraph n -> GraphvizOutput -> FilePath -> IO RunResult
- Data.GraphViz.Commands: runGraphvizCommand :: (PrintDot n) => GraphvizCommand -> DotGraph n -> GraphvizOutput -> FilePath -> IO Bool
+ Data.GraphViz.Commands: runGraphvizCommand :: (PrintDot n) => GraphvizCommand -> DotGraph n -> GraphvizOutput -> FilePath -> IO RunResult
- Data.GraphViz.Types.Parsing: parseStrictFloat :: (RealFrac a) => Parse a
+ Data.GraphViz.Types.Parsing: parseStrictFloat :: Parse Double
Files
- Changelog +35/−0
- Data/GraphViz.hs +46/−15
- Data/GraphViz/AttributeGenerator.hs +474/−0
- Data/GraphViz/Attributes.hs +278/−304
- Data/GraphViz/Attributes/Colors.hs +2541/−0
- Data/GraphViz/Commands.hs +350/−170
- Data/GraphViz/Testing.hs +238/−0
- Data/GraphViz/Testing/Instances.hs +847/−0
- Data/GraphViz/Testing/Instances/FGL.hs +42/−0
- Data/GraphViz/Testing/Properties.hs +68/−0
- Data/GraphViz/Types.hs +86/−48
- Data/GraphViz/Types/Clustering.hs +1/−1
- Data/GraphViz/Types/Internal.hs +48/−9
- Data/GraphViz/Types/Parsing.hs +68/−38
- Data/GraphViz/Types/Printing.hs +36/−19
- LICENSE +57/−1
- README +76/−0
- RunTests.hs +16/−0
- TODO +4/−4
- graphviz.cabal +41/−11
Changelog view
@@ -1,3 +1,38 @@+Changes in 2999.7.0.0+=====================++* Updated and extended functions to interact with the Graphviz tools.+ This now includes:++ - a better listing of available output types;++ - distinguishing file outputs from canvas outputs;++ - ability to automatically add the correct file extension to file+ outputs++ - Return any errors if calling Graphviz failed rather than just+ printing them to stderr++* Improved Color support:++ - fixed ColorScheme values++ - explicitly named X11 colors++ - conversion to/from values from the colour library++* Removed OrientationGraph; problems with distinguishing it when+ parsing from node-based Orientation values; its functionality is+ duplicated by Rotate.++* By default, the generated Dot code is now no longer indented; you+ can now use the prettyPrint functions in Data.GraphViz to produce+ readable Dot code.++* Added a testsuite; this is buildable by building with --flags=test.+ Numerous printing and parsing bugs were picked up with this.+ Changes in 2999.6.0.0 =====================
Data/GraphViz.hs view
@@ -1,16 +1,16 @@ {- | Module : Data.GraphViz- Description : GraphViz bindings for Haskell.+ Description : Graphviz bindings for Haskell. Copyright : (c) Matthew Sackman, Ivan Lazar Miljenovic License : 3-Clause BSD-style Maintainer : Ivan.Miljenovic@gmail.com This is the top-level module for the graphviz library. It provides functions to convert 'Data.Graph.Inductive.Graph.Graph's into the- /Dot/ language used by the /GraphViz/ suite of programs (as well as+ /Dot/ language used by the /Graphviz/ suite of programs (as well as a limited ability to perform the reverse operation). - Information about GraphViz and the Dot language can be found at:+ Information about Graphviz and the Dot language can be found at: <http://graphviz.org/> Commands for converting graphs to Dot format have two options: one@@ -29,7 +29,10 @@ , NodeCluster(..) , clusterGraphToDot , clusterGraphToDot'- -- * Passing the graph through GraphViz.+ -- ** Utility functions+ , prettyPrint+ , prettyPrint'+ -- * Passing the graph through Graphviz. -- ** Type aliases for @Node@ and @Edge@ labels. , AttributeNode , AttributeEdge@@ -53,14 +56,14 @@ import Data.GraphViz.Types.Clustering import Data.GraphViz.Attributes import Data.GraphViz.Commands+import Data.GraphViz.Types.Printing(PrintDot) import Data.Graph.Inductive.Graph import qualified Data.Set as Set import Control.Arrow((&&&)) import Data.Maybe(mapMaybe, fromJust) import qualified Data.Map as Map-import Control.Parallel.Strategies(rnf)-import System.IO(hGetContents)+import Control.Monad(liftM) import System.IO.Unsafe(unsafePerformIO) -- -----------------------------------------------------------------------------@@ -80,7 +83,7 @@ -- ----------------------------------------------------------------------------- --- | Convert a graph to GraphViz's /Dot/ format. The 'Bool' value is+-- | Convert a graph to Graphviz's /Dot/ format. The 'Bool' value is -- 'True' for directed graphs, 'False' otherwise. graphToDot :: (Graph gr) => Bool -> gr a b -> [GlobalAttributes] -> (LNode a -> Attributes) -> (LEdge b -> Attributes)@@ -93,7 +96,7 @@ cID = const Nothing fmtClust = const [] --- | Convert a graph to GraphViz's /Dot/ format with automatic+-- | Convert a graph to Graphviz's /Dot/ format with automatic -- direction detection. graphToDot' :: (Ord b, Graph gr) => gr a b -> [GlobalAttributes] -> (LNode a -> Attributes) -> (LEdge b -> Attributes)@@ -147,7 +150,7 @@ type AttributeNode a = (Attributes, a) type AttributeEdge b = (Attributes, b) --- | Run the appropriate GraphViz command on the graph to get+-- | Run the appropriate Graphviz command on the graph to get -- positional information and then combine that information back -- into the original graph. Note that for the edge information to -- be parsed properly when using multiple edges, each edge between@@ -167,12 +170,13 @@ dotAttributes :: (Graph gr) => Bool -> gr a b -> DotGraph Node -> IO (gr (AttributeNode a) (AttributeEdge b)) dotAttributes isDir gr dot- = do (Just output) <- graphvizWithHandle command dot DotOutput hToString+ = do (Right output) <- graphvizWithHandle command+ dot+ DotOutput+ hGetContents' return $ rebuildGraphWithAttributes output where command = if isDir then dirCommand else undirCommand- hToString h = do s <- hGetContents h- rnf s `seq` return s rebuildGraphWithAttributes dotResult = mkGraph lnodes ledges where lnodes = map (\(n, l) -> (n, (nodeMap Map.! n, l)))@@ -190,7 +194,7 @@ edgeMap = Map.fromList $ map ( (edgeFromNodeID &&& edgeToNodeID) &&& edgeAttributes) es --- | Run the appropriate GraphViz command on the graph to get+-- | Run the appropriate Graphviz command on the graph to get -- positional information and then combine that information back -- into the original graph. --@@ -200,7 +204,7 @@ -> IO (gr (AttributeNode a) (AttributeEdge b)) graphToGraph' gr = graphToGraph (isDirected gr) gr --- | Run the appropriate GraphViz command on the clustered graph to+-- | Run the appropriate Graphviz command on the clustered graph to -- get positional information and then combine that information back -- into the original graph. Note that for the edge information to -- be parsed properly when using multiple edges, each edge between@@ -219,7 +223,7 @@ where dot = clusterGraphToDot isDir gr gAtts clBy cID fmtClust fmtNode fmtEdge --- | Run the appropriate GraphViz command on the clustered graph to+-- | Run the appropriate Graphviz command on the clustered graph to -- get positional information and then combine that information back -- into the original graph. --@@ -290,3 +294,30 @@ -> (LNode a -> NodeCluster c l) -> gr (AttributeNode a) (AttributeEdge b) dotizeClusterGraph' g = dotizeClusterGraph (isDirected g) g++-- -----------------------------------------------------------------------------+-- Utility Functions++-- | Pretty-print the 'DotGraph' by passing it through the 'Canon'+-- output type (which produces \"canonical\" output). This is+-- required because the @printIt@ function in+-- "Data.GraphViz.Types.Printing" no longer uses indentation to+-- ensure the Dot code is printed correctly.+prettyPrint :: (PrintDot a) => DotGraph a -> IO String+prettyPrint dg = liftM fromRight+ -- Note that the choice of command here should be+ -- arbitrary.+ $ graphvizWithHandle (commandFor dg)+ dg+ Canon+ hGetContents'+ where+ fromRight (Right r) = r+ fromRight Left{} = fail "Usage of prettyPrint failed; \+ \is the Graphviz suite of tools installed?"++-- | The 'unsafePerformIO'd version of 'prettyPrint'. Graphviz should+-- always produce the same pretty-printed output, so this should be+-- safe.+prettyPrint' :: (PrintDot a) => DotGraph a -> String+prettyPrint' = unsafePerformIO . prettyPrint
+ Data/GraphViz/AttributeGenerator.hs view
@@ -0,0 +1,474 @@+{- |+ Module : Data.GraphViz.AttributeGenerator+ Description : Definition of the Graphviz attributes.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module is a stand-alone that generates the correct code for+ Data.GraphViz.Attributes.+ -}+module Data.GraphViz.AttributeGenerator where++import Text.PrettyPrint+import Data.List(transpose)+import Data.Maybe(catMaybes, isJust, fromJust)+import Control.Monad(liftM)+import System.Environment(getArgs)++type Code = Doc++-- If any args are passed in, then generate the Arbitrary instance+-- instead of the definition.+main :: IO ()+main = do args <- getArgs+ let f = if null args+ then genCode+ else genArbitrary+ print $ f att+ where+ att = AS { tpNm = text "Attribute"+ , atts = attributes+ }++genCode :: Atts -> Doc+genCode att = vsep $ map ($att) cds+ where+ cds = [ createDefn+ , createAlias+ , showInstance+ , parseInstance+ , usedByFunc "Graphs" forGraphs+ , usedByFunc "Clusters" forClusters+ , usedByFunc "SubGraphs" forSubGraphs+ , usedByFunc "Nodes" forNodes+ , usedByFunc "Edges" forEdges+ ]++genArbitrary :: Atts -> Doc+genArbitrary = arbitraryInstance++-- -----------------------------------------------------------------------------++-- Defining data structures++data Atts = AS { tpNm :: Code+ , atts :: [Attribute]+ }++data Attribute = A { cnst :: Code+ , name :: Code+ , parseNames :: [Code]+ , valtype :: VType+ , parseDef :: Maybe Code+ , forGraphs :: Bool+ , forClusters :: Bool+ , forSubGraphs :: Bool+ , forNodes :: Bool+ , forEdges :: Bool+ , comment :: Doc+ }++makeAttr :: Constructor -> [Name] -> UsedBy -> VType+ -> Maybe Default -- Used when parsing the field+ -> Maybe Default -> Maybe Minimum -> Maybe Comment+ -> Attribute+makeAttr c ns u v df d m cm = A { cnst = text c+ , name = head ns'+ , parseNames = ns'+ , valtype = v -- just in case need to do fancy+ -- stuff+ , parseDef = liftM text df+ , forGraphs = isFor 'G'+ , forClusters = isFor 'C' || forSG+ , forSubGraphs = forSG+ , forNodes = isFor 'N'+ , forEdges = isFor 'E'+ , comment = cm'+ }+ where+ ns' = map text ns+ isFor f = f `elem` u+ forSG = isFor 'S'+ df' = if v == Bl then Just "'True'" else fmap ( \ t -> '\'' : t ++ "'") df+ mDoc (f,fc) = f <> colon <+> text fc+ addF f = fmap (\ dc -> (wrap (char '/') (text f), dc))+ cm' = hsep+ . punctuate semi+ . map mDoc+ $ catMaybes [ addF "Valid for" (Just u)+ , addF "Default" d+ , addF "Parsing Default" df'+ , addF "Minimum" m+ , addF "Notes" cm+ ]++type Constructor = String+type Name = String+type UsedBy = String -- should only contain subset of "ENGCS"+type Default = String+type Minimum = String+type Comment = String++data VType = Dbl+ | Integ+ | Strng+ | EStrng+ | URL+ | Bl+ | Cust String+ deriving (Eq, Ord, Show, Read)++vtype :: VType -> Doc+vtype Dbl = text "Double"+vtype Integ = text "Int"+vtype Strng = text "String"+vtype EStrng = text "EscString"+vtype URL = text "URL"+vtype Bl = text "Bool"+vtype (Cust t) = text t++vtypeCode :: Attribute -> Code+vtypeCode = vtype . valtype++-- -----------------------------------------------------------------------------++createDefn :: Atts -> Code+createDefn att = hdr $+$ constructors $+$ derivs+ where+ hdr = text "data" <+> tpNm att+ constructors = nest tab+ . asRows+ . firstOthers equals (char '|')+ . map createDefn+ $ atts att+ derivs = nest (tab + 2) $ text "deriving (Eq, Ord, Show, Read)"+ createDefn a = [cnst a <+> vtypeCode a+ , if isEmpty cm+ then empty+ else text "-- ^" <+> cm+ ]+ where+ cm = comment a++createAlias :: Atts -> Code+createAlias att = text "type"+ <+> tp <> char 's'+ <+> equals+ <+> brackets tp+ where+ tp = tpNm att++showInstance :: Atts -> Code+showInstance att = hdr $+$ insts'+ where+ hdr = text "instance" <+> text "PrintDot" <+> tpNm att <+> text "where"+ var = char 'v'+ sFunc = text "unqtDot"+ cnct = text "<>"+ insts = asRows+ . map mkInstance+ $ atts att+ mkInstance a = [ sFunc <+> parens (cnst a <+> var)+ , equals <+> text "printField" <+> doubleQuotes (name a)+ <+> var+ ]+ insts' = nest tab+ $ vsep [ insts+ , text "listToDot" <+> equals <+> text "unqtListToDot"+ ]++parseInstance :: Atts -> Code+parseInstance att = hdr $+$ nest tab fns+ where+ hdr = text "instance" <+> text "ParseDot" <+> tpNm att <+> text "where"+ fn = pFunc <+> equals <+> text "oneOf" <+> ops+ fns = vsep [ fn+ , text "parse" <+> equals <+> pFunc+ , text "parseList" <+> equals <+> text "parseUnqtList"+ ]+ ops = flip ($$) rbrack+ . asRows+ . firstOthers lbrack comma+ . map parseAttr+ $ atts att+ pFunc = text "parseUnqt"+ parseAttr a = [ text "liftM" <+> cnst a+ , dollar <+> pfFunc a+ ]+ pType b a+ | valtype a == Bl = pFld <> text "Bool"+ | isJust $ parseDef a = pFld <> text "Def" <+> fromJust (parseDef a)+ | otherwise = pFld+ where+ pFld = text "parseField" <> if b then char 's' else empty++ pfFunc a = case map doubleQuotes $ parseNames a of+ [n] -> pType False a <+> n+ ns -> pType True a <+> docList ns++arbitraryInstance :: Atts -> Code+arbitraryInstance att = hdr $+$ fns+ where+ hdr = text "instance" <+> text "Arbitrary" <+> tpNm att <+> text "where"+ fns = nest tab $ vsep [aFn, sFn]+ aFn = aFunc <+> equals <+> text "oneof" <+> ops+ ops = flip ($$) rbrack+ . asRows+ . firstOthers lbrack comma+ . map (return . arbAttr)+ $ atts att+ aFunc = text "arbitrary"+ arbAttr a = text "liftM" <+> cnst a <+> arbitraryFor' a+ sFn = asRows+ . map shrinkAttr+ $ atts att+ sFunc = text "shrink"+ var = char 'v'+ shrinkAttr a = [ sFunc <+> parens (cnst a <+> var)+ , equals <+> text "map" <+> cnst a+ , dollar <+> shrinkFor (valtype a) <+> var+ ]++arbitraryFor :: VType -> Doc+arbitraryFor Strng = text "arbString"+arbitraryFor EStrng = text "arbString"+arbitraryFor (Cust ('[':_)) = text "arbList"+arbitraryFor _ = text "arbitrary"++arbitraryFor' :: Attribute -> Doc+arbitraryFor' = arbitraryFor . valtype++shrinkFor :: VType -> Doc+shrinkFor (Cust ('[':_)) = text "nonEmptyShrinks"+shrinkFor Strng = text "shrinkString"+shrinkFor EStrng = text "shrinkString"+shrinkFor _ = text "shrink"++usedByFunc :: String -> (Attribute -> Bool) -> Atts -> Code+usedByFunc nm p att = cmnt $$ asRows (tpSig : trs ++ [fls])+ where+ nm' = text nm+ dt = tpNm att+ cmnt = text "-- | Determine if this" <+> dt+ <+> text "is valid for use with" <+> nm' <> dot+ tpSig = [ fn+ , colon <> colon+ <+> dt <+> text "->" <+> text "Bool"+ ]+ fn = text "usedBy" <> nm'+ tr = text "True"+ trs = map aTr as'+ fl = text "False"+ fls = [ fn <+> char '_'+ , equals <+> fl+ ]+ as' = filter p $ atts att+ aTr a = [ fn <+> cnst a <> braces empty+ , equals <+> tr+ ]+++-- -----------------------------------------------------------------------------++-- Helper functions++-- Size of a tab character+tab :: Int+tab = 4++firstOthers :: Doc -> Doc -> [[Doc]] -> [[Doc]]+firstOthers _ _ [] = []+firstOthers f o (d:ds) = (f : d) : map ((:) o) ds++wrap :: Doc -> Doc -> Doc+wrap w d = w <> d <> w++vsep :: [Doc] -> Doc+vsep = vcat . punctuate newline+ where+ newline = char '\n'++asRows :: [[Doc]] -> Doc+asRows as = vcat $ map padR asL+ where+ asL = map (map (\d -> (d, docLen d))) as+ cWidths = map (maximum . map snd) $ transpose asL+ shiftLen rls = let (rs,ls) = unzip rls+ in zip rs (0:ls)+ padR = hsep . zipWith append (0 : cWidths) . shiftLen+ append l' (d,l) = hcat (repl (l' - l) space) <> d+ repl n xs | n <= 0 = []+ | otherwise = replicate n xs++-- A really hacky thing to do, but oh well...+-- Don't use this for multi-line Docs!+docLen :: Doc -> Int+docLen = length . render++docList :: [Doc] -> Doc+docList = brackets . hsep . punctuate comma++dot :: Doc+dot = char '.'++-- -----------------------------------------------------------------------------++-- The actual attributes++attributes :: [Attribute]+attributes = [ makeAttr "Damping" ["Damping"] "G" Dbl Nothing (Just "@0.99@") (Just "@0.0@") (Just "neato only")+ , makeAttr "K" ["K"] "GC" Dbl Nothing (Just "@0.3@") (Just "@0@") (Just "sfdp, fdp only")+ , makeAttr "URL" ["URL", "href"] "ENGC" URL Nothing (Just "none") Nothing (Just "svg, postscript, map only")+ , makeAttr "ArrowHead" ["arrowhead"] "E" (Cust "ArrowType") Nothing (Just "@'normal'@") Nothing Nothing+ , makeAttr "ArrowSize" ["arrowsize"] "E" Dbl Nothing (Just "@1.0@") (Just "@0.0@") Nothing+ , makeAttr "ArrowTail" ["arrowtail"] "E" (Cust "ArrowType") Nothing (Just "@'normal'@") Nothing Nothing+ , makeAttr "Aspect" ["aspect"] "G" (Cust "AspectType") Nothing Nothing Nothing (Just "dot only")+ , makeAttr "Bb" ["bb"] "G" (Cust "Rect") Nothing Nothing Nothing (Just "write only")+ , makeAttr "BgColor" ["bgcolor"] "GC" (Cust "Color") Nothing (Just "X11Color 'Transparent'") Nothing Nothing+ , makeAttr "Center" ["center"] "G" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "Charset" ["charset"] "G" Strng Nothing (Just "@\\\"UTF-8\\\"@") Nothing Nothing+ , makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "@'Local'@") Nothing (Just "dot only")+ , makeAttr "ColorScheme" ["colorscheme"] "ENCG" (Cust "ColorScheme") Nothing (Just "@'X11'@") Nothing Nothing+ , makeAttr "Color" ["color"] "ENC" (Cust "[Color]") Nothing (Just "@X11Color 'Black'@") Nothing Nothing+ , makeAttr "Comment" ["comment"] "ENG" Strng Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "Compound" ["compound"] "G" Bl (Just "True") (Just "@'False'@") Nothing (Just "dot only")+ , makeAttr "Concentrate" ["concentrate"] "G" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "Constraint" ["constraint"] "E" Bl (Just "True") (Just "@'True'@") Nothing (Just "dot only")+ , makeAttr "Decorate" ["decorate"] "E" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "DefaultDist" ["defaultdist"] "G" Dbl Nothing (Just "@1+(avg. len)*sqrt(|V|)@") (Just "@epsilon@") (Just "neato only")+ , makeAttr "Dimen" ["dimen"] "G" Integ Nothing (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only")+ , makeAttr "Dim" ["dim"] "G" Integ Nothing (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only")+ , makeAttr "Dir" ["dir"] "E" (Cust "DirType") Nothing (Just "@'Forward'@ (directed), @'NoDir'@ (undirected)") Nothing Nothing+ , makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "@'NoConstraints'@") Nothing (Just "neato only")+ , makeAttr "Distortion" ["distortion"] "N" Dbl Nothing (Just "@0.0@") (Just "@-100.0@") Nothing+ , makeAttr "DPI" ["dpi", "resolution"] "G" Dbl Nothing (Just "@96.0@, @0.0@") Nothing (Just "svg, bitmap output only; \\\"resolution\\\" is a synonym")+ , makeAttr "EdgeURL" ["edgeURL", "edgehref"] "E" URL Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, map only")+ , makeAttr "EdgeTarget" ["edgetarget"] "E" EStrng Nothing (Just "none") Nothing (Just "svg, map only")+ , makeAttr "EdgeTooltip" ["edgetooltip"] "E" EStrng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")+ , makeAttr "Epsilon" ["epsilon"] "G" Dbl Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "neato only")+ , makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "@+3@") Nothing (Just "not dot")+ , makeAttr "FillColor" ["fillcolor"] "NC" (Cust "Color") Nothing (Just "@X11Color 'LightGray'@ (nodes), @X11Color 'Black'@ (clusters)") Nothing Nothing+ , makeAttr "FixedSize" ["fixedsize"] "N" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "FontColor" ["fontcolor"] "ENGC" (Cust "Color") Nothing (Just "@X11Color 'Black'@") Nothing Nothing+ , makeAttr "FontName" ["fontname"] "ENGC" Strng Nothing (Just "@\\\"Times-Roman\\\"@") Nothing Nothing+ , makeAttr "FontNames" ["fontnames"] "G" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg only")+ , makeAttr "FontPath" ["fontpath"] "G" Strng Nothing (Just "system-dependent") Nothing Nothing+ , makeAttr "FontSize" ["fontsize"] "ENGC" Dbl Nothing (Just "@14.0@") (Just "@1.0@") Nothing+ , makeAttr "Group" ["group"] "N" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "dot only")+ , makeAttr "HeadURL" ["headURL", "headhref"] "E" URL Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, map only")+ , makeAttr "HeadClip" ["headclip"] "E" Bl (Just "True") (Just "@'True'@") Nothing Nothing+ , makeAttr "HeadLabel" ["headlabel"] "E" (Cust "Label") Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "HeadPort" ["headport"] "E" (Cust "PortPos") Nothing (Just "@'PP' 'CenterPoint'@") Nothing Nothing+ , makeAttr "HeadTarget" ["headtarget"] "E" EStrng Nothing (Just "none") Nothing (Just "svg, map only")+ , makeAttr "HeadTooltip" ["headtooltip"] "E" EStrng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")+ , makeAttr "Height" ["height"] "N" Dbl Nothing (Just "@0.5@") (Just "@0.02@") Nothing+ , makeAttr "ID" ["id"] "GNE" (Cust "Label") Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, postscript, map only")+ , makeAttr "Image" ["image"] "N" Strng Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "ImageScale" ["imagescale"] "N" (Cust "ScaleType") (Just "UniformScale") (Just "@'NoScale'@") Nothing Nothing+ , makeAttr "LabelURL" ["labelURL", "labelhref"] "E" URL Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, map only")+ , makeAttr "LabelAngle" ["labelangle"] "E" Dbl Nothing (Just "@-25.0@") (Just "@-180.0@") Nothing+ , makeAttr "LabelDistance" ["labeldistance"] "E" Dbl Nothing (Just "@1.0@") (Just "@0.0@") Nothing+ , makeAttr "LabelFloat" ["labelfloat"] "E" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "LabelFontColor" ["labelfontcolor"] "E" (Cust "Color") Nothing (Just "@X11Color 'Black'@") Nothing Nothing+ , makeAttr "LabelFontName" ["labelfontname"] "E" Strng Nothing (Just "@\\\"Times-Roman\\\"@") Nothing Nothing+ , makeAttr "LabelFontSize" ["labelfontsize"] "E" Dbl Nothing (Just "@14.0@") (Just "@1.0@") Nothing+ , makeAttr "LabelJust" ["labeljust"] "GC" (Cust "Justification") Nothing (Just "@'JCenter'@") Nothing Nothing+ , makeAttr "LabelLoc" ["labelloc"] "GCN" (Cust "VerticalPlacement") Nothing (Just "@'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)") Nothing Nothing+ , makeAttr "LabelTarget" ["labeltarget"] "E" EStrng Nothing (Just "none") Nothing (Just "svg, map only")+ , makeAttr "LabelTooltip" ["labeltooltip"] "E" EStrng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")+ , makeAttr "Label" ["label"] "ENGC" (Cust "Label") Nothing (Just "@'StrLabel' \\\"\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)") Nothing Nothing+ , makeAttr "Landscape" ["landscape"] "G" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "LayerSep" ["layersep"] "G" Strng Nothing (Just "@\\\" :\\t\\\"@") Nothing Nothing+ , makeAttr "Layers" ["layers"] "G" (Cust "LayerList") Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "Layer" ["layer"] "EN" (Cust "LayerRange") Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "Layout" ["layout"] "G" Strng Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "Len" ["len"] "E" Dbl Nothing (Just "@1.0@ (neato), @0.3@ (fdp)") Nothing (Just "fdp, neato only")+ , makeAttr "LevelsGap" ["levelsgap"] "G" Dbl Nothing (Just "@0.0@") Nothing (Just "neato only")+ , makeAttr "Levels" ["levels"] "G" Integ Nothing (Just "@MAXINT@") (Just "@0@") (Just "sfdp only")+ , makeAttr "LHead" ["lhead"] "E" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "dot only")+ , makeAttr "LPos" ["lp"] "EGC" (Cust "Point") Nothing Nothing Nothing (Just "write only")+ , makeAttr "LTail" ["ltail"] "E" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "dot only")+ , makeAttr "Margin" ["margin"] "NG" (Cust "DPoint") Nothing (Just "device-dependent") Nothing Nothing+ , makeAttr "MaxIter" ["maxiter"] "G" Integ Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp)") Nothing (Just "fdp, neato only")+ , makeAttr "MCLimit" ["mclimit"] "G" Dbl Nothing (Just "@1.0@") Nothing (Just "dot only")+ , makeAttr "MinDist" ["mindist"] "G" Dbl Nothing (Just "@1.0@") (Just "@0.0@") (Just "circo only")+ , makeAttr "MinLen" ["minlen"] "E" Integ Nothing (Just "@1@") (Just "@0@") (Just "dot only")+ , makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "@'ShortPath'@") Nothing (Just "neato only")+ , makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "@'Major'@") Nothing (Just "neato only")+ , makeAttr "Mosek" ["mosek"] "G" Bl (Just "True") (Just "@'False'@") Nothing (Just "neato only; requires the Mosek software")+ , makeAttr "NodeSep" ["nodesep"] "G" Dbl Nothing (Just "@0.25@") (Just "@0.02@") (Just "dot only")+ , makeAttr "NoJustify" ["nojustify"] "GCNE" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "Normalize" ["normalize"] "G" Bl (Just "True") (Just "@'False'@") Nothing (Just "not dot")+ , makeAttr "Nslimit1" ["nslimit1"] "G" Dbl Nothing Nothing Nothing (Just "dot only")+ , makeAttr "Nslimit" ["nslimit"] "G" Dbl Nothing Nothing Nothing (Just "dot only")+ , makeAttr "Ordering" ["ordering"] "G" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "dot only")+ , makeAttr "Orientation" ["orientation"] "N" Dbl Nothing (Just "@0.0@") (Just "@360.0@") Nothing+ , makeAttr "OutputOrder" ["outputorder"] "G" (Cust "OutputMode") Nothing (Just "@'BreadthFirst'@") Nothing Nothing+ , makeAttr "OverlapScaling" ["overlap_scaling"] "G" Dbl Nothing (Just "@-4@") (Just "@-1.0e10@") (Just "prism only")+ , makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not dot")+ , makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "@'PackNode'@") Nothing (Just "not dot")+ , makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "@'False'@") Nothing (Just "not dot")+ , makeAttr "Pad" ["pad"] "G" (Cust "DPoint") Nothing (Just "@'DVal' 0.0555@ (4 points)") Nothing Nothing+ , makeAttr "PageDir" ["pagedir"] "G" (Cust "PageDir") Nothing (Just "@'BL'@") Nothing Nothing+ , makeAttr "Page" ["page"] "G" (Cust "Point") Nothing Nothing Nothing Nothing+ , makeAttr "PenColor" ["pencolor"] "C" (Cust "Color") Nothing (Just "@X11Color 'Black'@") Nothing Nothing+ , makeAttr "PenWidth" ["penwidth"] "CNE" Dbl Nothing (Just "@1.0@") (Just "@0.0@") Nothing+ , makeAttr "Peripheries" ["peripheries"] "NC" Integ Nothing (Just "shape default (nodes), @1@ (clusters)") (Just "0") Nothing+ , makeAttr "Pin" ["pin"] "N" Bl (Just "True") (Just "@'False'@") Nothing (Just "fdp, neato only")+ , makeAttr "Pos" ["pos"] "EN" (Cust "Pos") Nothing Nothing Nothing Nothing+ , makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "sfdp only")+ , makeAttr "Quantum" ["quantum"] "G" Dbl Nothing (Just "@0.0@") (Just "@0.0@") Nothing+ , makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "@'TB'@") Nothing (Just "dot only")+ , makeAttr "RankSep" ["ranksep"] "G" Dbl Nothing (Just "@0.5@ (dot), @1.0@ (twopi)") (Just "0.02") (Just "twopi, dot only")+ , makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing (Just "dot only")+ , makeAttr "Ratio" ["ratio"] "G" (Cust "Ratios") Nothing Nothing Nothing Nothing+ , makeAttr "Rects" ["rects"] "N" (Cust "Rect") Nothing Nothing Nothing (Just "write only")+ , makeAttr "Regular" ["regular"] "N" Bl (Just "True") (Just "@'False'@") Nothing Nothing+ , makeAttr "ReMinCross" ["remincross"] "G" Bl (Just "True") (Just "@'False'@") Nothing (Just "dot only")+ , makeAttr "RepulsiveForce" ["repulsiveforce"] "G" Dbl Nothing (Just "@1.0@") (Just "@0.0@") (Just "sfdp only")+ , makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "circo, twopi only")+ , makeAttr "Rotate" ["rotate"] "G" Integ Nothing (Just "@0@") Nothing Nothing+ , makeAttr "SameHead" ["samehead"] "E" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "dot only")+ , makeAttr "SameTail" ["sametail"] "E" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "dot only")+ , makeAttr "SamplePoints" ["samplepoints"] "N" Integ Nothing (Just "@8@ (output), @20@ (overlap and image maps)") Nothing Nothing+ , makeAttr "SearchSize" ["searchsize"] "G" Integ Nothing (Just "@30@") Nothing (Just "dot only")+ , makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "@+4@") Nothing (Just "not dot")+ , makeAttr "ShapeFile" ["shapefile"] "N" Strng Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "Shape" ["shape"] "N" (Cust "Shape") Nothing (Just "@'Ellipse'@") Nothing Nothing+ , makeAttr "ShowBoxes" ["showboxes"] "ENG" Integ Nothing (Just "@0@") (Just "@0@") (Just "dot only")+ , makeAttr "Sides" ["sides"] "N" Integ Nothing (Just "@4@") (Just "@0@") Nothing+ , makeAttr "Size" ["size"] "G" (Cust "Point") Nothing Nothing Nothing Nothing+ , makeAttr "Skew" ["skew"] "N" Dbl Nothing (Just "@0.0@") (Just "@-100.0@") Nothing+ , makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "@'NoSmooth'@") Nothing (Just "sfdp only")+ , makeAttr "SortV" ["sortv"] "GCN" Integ Nothing (Just "@0@") (Just "@0@") Nothing+ , makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") Nothing Nothing Nothing+ , makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing (Just "@\\\"\\\"@") Nothing (Just "fdp, neato only")+ , makeAttr "StyleSheet" ["stylesheet"] "G" Strng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg only")+ , makeAttr "Style" ["style"] "ENC" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing+ , makeAttr "TailURL" ["tailURL", "tailhref"] "E" URL Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, map only")+ , makeAttr "TailClip" ["tailclip"] "E" Bl (Just "True") (Just "@'True'@") Nothing Nothing+ , makeAttr "TailLabel" ["taillabel"] "E" (Cust "Label") Nothing (Just "@\\\"\\\"@") Nothing Nothing+ , makeAttr "TailPort" ["tailport"] "E" (Cust "PortPos") Nothing (Just "center") Nothing Nothing+ , makeAttr "TailTarget" ["tailtarget"] "E" EStrng Nothing (Just "none") Nothing (Just "svg, map only")+ , makeAttr "TailTooltip" ["tailtooltip"] "E" EStrng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")+ , makeAttr "Target" ["target"] "ENGC" EStrng Nothing (Just "none") Nothing (Just "svg, map only")+ , makeAttr "Tooltip" ["tooltip"] "NEC" EStrng Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")+ , makeAttr "TrueColor" ["truecolor"] "G" Bl (Just "True") Nothing Nothing (Just "bitmap output only")+ , makeAttr "Vertices" ["vertices"] "N" (Cust "[Point]") Nothing Nothing Nothing (Just "write only")+ , makeAttr "ViewPort" ["viewport"] "G" (Cust "ViewPort") Nothing (Just "none") Nothing Nothing+ , makeAttr "VoroMargin" ["voro_margin"] "G" Dbl Nothing (Just "@0.05@") (Just "@0.0@") (Just "not dot")+ , makeAttr "Weight" ["weight"] "E" Dbl Nothing (Just "@1.0@") (Just "@0@ (dot), @1@ (neato,fdp,sfdp)") Nothing+ , makeAttr "Width" ["width"] "N" Dbl Nothing (Just "@0.75@") (Just "@0.01@") Nothing+ , makeAttr "Z" ["z"] "N" Dbl Nothing (Just "@0.0@") (Just "@-MAXFLOAT@, @-1000@") Nothing+ ]++attrs = take 10 $ drop 5 attributes++attrs' = AS (text "Attribute") attrs++bool :: a -> a -> Bool -> a+bool f t b = if b then t else f++dollar :: Doc+dollar = char '$'
Data/GraphViz/Attributes.hs view
@@ -1,12 +1,12 @@ {- | Module : Data.GraphViz.Attributes- Description : Definition of the 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+ a Graphviz graph can have. These attributes are based on the documentation found at: <http://graphviz.org/doc/info/attrs.html> @@ -26,10 +26,6 @@ /A/ to /B/, then /A/ is the tail node and /B/ is the head node (since /A/ is at the tail end of the arrow). - * When parsing named 'Color' values, the entire value entered is- kept as-is; this library as yet has no understanding of different- color schemes, etc.- * ColorList and PointfList are defined as actual lists (but 'LayerList' is not). Note that for the Color 'Attribute' for node values, only a single Color is valid; edges are allowed@@ -88,7 +84,6 @@ , ArrowType(..) , AspectType(..) , Rect(..)- , Color(..) , ClusterMode(..) , DirType(..) , DEConstraints(..)@@ -126,32 +121,52 @@ , ScaleType(..) , Justification(..) , Ratios(..)- -- * Types representing the Dot grammar for @ArrowType@.+ , module Data.GraphViz.Attributes.Colors+ -- * Types representing the Dot grammar for @ArrowType@. , ArrowShape(..) , ArrowModifier(..) , ArrowFill(..) , ArrowSide(..)- -- ** Default @ArrowType@ aliases.- -- *** The 9 primitive @ArrowShape@s.- , box, crow, diamond, dotArrow, inv, noArrow, normal, tee, vee- -- *** 5 derived Arrows.- , oDot, invDot, invODot, oBox, oDiamond- -- *** 5 supported cases for backwards compatibility- , eDiamond, openArr, halfOpen, emptyArr, invEmpty- -- ** @ArrowModifier@ instances- , noMods, openMod+ -- ** Default @ArrowType@ aliases.+ -- *** The 9 primitive @ArrowShape@s.+ , box+ , crow+ , diamond+ , dotArrow+ , inv+ , noArrow+ , normal+ , tee+ , vee+ -- *** 5 derived Arrows.+ , oDot+ , invDot+ , invODot+ , oBox+ , oDiamond+ -- *** 5 supported cases for backwards compatibility+ , eDiamond+ , openArr+ , halfOpen+ , emptyArr+ , invEmpty+ -- ** @ArrowModifier@ instances+ , noMods+ , openMod+ -- * Other exported functions\/values+ , defLayerSep+ , notLayerSep ) where +import Data.GraphViz.Attributes.Colors import Data.GraphViz.Types.Internal import Data.GraphViz.Types.Parsing import Data.GraphViz.Types.Printing -import Data.Char(isDigit, isHexDigit)-import Data.Maybe(isJust, maybe)-import Data.Word(Word8)-import Numeric(showHex, readHex)+import Data.Char(toLower)+import Data.Maybe(isJust) import Control.Arrow(first)-import Control.Monad(liftM)+import Control.Monad(liftM, liftM2) -- ----------------------------------------------------------------------------- @@ -175,7 +190,7 @@ [@E@] Valid for Edges. - The /Default/ listings are those that the various GraphViz commands+ The /Default/ listings are those that the various Graphviz commands use if that 'Attribute' isn't specified (in cases where this is /none/, this is equivalent to a 'Nothing' value; that is, no value is used). The /Parsing Default/ listings represent what value is@@ -191,20 +206,20 @@ | 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+ | BgColor Color -- ^ /Valid for/: GC; /Default/: X11Color 'Transparent' | Center Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True' | Charset String -- ^ /Valid for/: G; /Default/: @\"UTF-8\"@ | ClusterRank ClusterMode -- ^ /Valid for/: G; /Default/: @'Local'@; /Notes/: dot only- | Color [Color] -- ^ /Valid for/: ENC; /Default/: @black@- | ColorScheme String -- ^ /Valid for/: ENCG; /Default/: @\"\"@+ | ColorScheme ColorScheme -- ^ /Valid for/: ENCG; /Default/: @'X11'@+ | Color [Color] -- ^ /Valid for/: ENC; /Default/: @X11Color 'Black'@ | Comment String -- ^ /Valid for/: ENG; /Default/: @\"\"@ | Compound Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: dot only | Concentrate Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True' | Constraint Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: dot only | Decorate Bool -- ^ /Valid for/: E; /Default/: @'False'@; /Parsing Default/: 'True' | DefaultDist Double -- ^ /Valid for/: G; /Default/: @1+(avg. len)*sqrt(|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+ | Dim Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: sfdp, fdp, neato only | Dir DirType -- ^ /Valid for/: E; /Default/: @'Forward'@ (directed), @'NoDir'@ (undirected) | DirEdgeConstraints DEConstraints -- ^ /Valid for/: G; /Default/: @'NoConstraints'@; /Parsing Default/: 'EdgeConstraints'; /Notes/: neato only | Distortion Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@@@ -214,9 +229,9 @@ | EdgeTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only | Epsilon Double -- ^ /Valid for/: G; /Default/: @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@); /Notes/: neato only | ESep DPoint -- ^ /Valid for/: G; /Default/: @+3@; /Notes/: not dot- | FillColor Color -- ^ /Valid for/: NC; /Default/: @lightgrey@ (nodes), @black@ (clusters)+ | FillColor Color -- ^ /Valid for/: NC; /Default/: @X11Color 'LightGray'@ (nodes), @X11Color 'Black'@ (clusters) | FixedSize Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'- | FontColor Color -- ^ /Valid for/: ENGC; /Default/: @black@+ | FontColor Color -- ^ /Valid for/: ENGC; /Default/: @X11Color '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@@ -232,26 +247,26 @@ | ID Label -- ^ /Valid for/: GNE; /Default/: @\"\"@; /Notes/: svg, postscript, map only | Image String -- ^ /Valid for/: N; /Default/: @\"\"@ | ImageScale ScaleType -- ^ /Valid for/: N; /Default/: @'NoScale'@; /Parsing Default/: 'UniformScale'- | Label Label -- ^ /Valid for/: ENGC; /Default/: @'StrLabel' \"\N\"@ (nodes), @'StrLabel' \"\"@ (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'@; /Parsing Default/: 'True'- | LabelFontColor Color -- ^ /Valid for/: E; /Default/: @black@+ | LabelFontColor Color -- ^ /Valid for/: E; /Default/: @X11Color 'Black'@ | LabelFontName String -- ^ /Valid for/: E; /Default/: @\"Times-Roman\"@ | LabelFontSize Double -- ^ /Valid for/: E; /Default/: @14.0@; /Minimum/: @1.0@ | LabelJust Justification -- ^ /Valid for/: GC; /Default/: @'JCenter'@ | LabelLoc VerticalPlacement -- ^ /Valid for/: GCN; /Default/: @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes) | LabelTarget EscString -- ^ /Valid for/: E; /Default/: none; /Notes/: svg, map only | LabelTooltip EscString -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, cmap only+ | Label Label -- ^ /Valid for/: ENGC; /Default/: @'StrLabel' \"\N\"@ (nodes), @'StrLabel' \"\"@ (otherwise) | Landscape Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'- | Layer LayerRange -- ^ /Valid for/: EN; /Default/: @\"\"@- | Layers LayerList -- ^ /Valid for/: G; /Default/: @\"\"@ | LayerSep String -- ^ /Valid for/: G; /Default/: @\" :\t\"@+ | Layers LayerList -- ^ /Valid for/: G; /Default/: @\"\"@+ | Layer LayerRange -- ^ /Valid for/: EN; /Default/: @\"\"@ | 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@; /Notes/: sfdp only | LevelsGap Double -- ^ /Valid for/: G; /Default/: @0.0@; /Notes/: neato only+ | Levels Int -- ^ /Valid for/: G; /Default/: @MAXINT@; /Minimum/: @0@; /Notes/: sfdp only | LHead String -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: dot only | LPos Point -- ^ /Valid for/: EGC; /Notes/: write only | LTail String -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: dot only@@ -260,35 +275,34 @@ | MCLimit Double -- ^ /Valid for/: G; /Default/: @1.0@; /Notes/: dot only | MinDist Double -- ^ /Valid for/: G; /Default/: @1.0@; /Minimum/: @0.0@; /Notes/: circo only | MinLen Int -- ^ /Valid for/: E; /Default/: @1@; /Minimum/: @0@; /Notes/: dot only- | Mode ModeType -- ^ /Valid for/: G; /Default/: @'Major'@; /Notes/: neato only | Model Model -- ^ /Valid for/: G; /Default/: @'ShortPath'@; /Notes/: neato only+ | Mode ModeType -- ^ /Valid for/: G; /Default/: @'Major'@; /Notes/: neato only | Mosek Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: neato only; requires the Mosek software | NodeSep Double -- ^ /Valid for/: G; /Default/: @0.25@; /Minimum/: @0.02@; /Notes/: dot only | NoJustify Bool -- ^ /Valid for/: GCNE; /Default/: @'False'@; /Parsing Default/: 'True' | Normalize Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: not dot- | Nslimit Double -- ^ /Valid for/: G; /Notes/: dot only | Nslimit1 Double -- ^ /Valid for/: G; /Notes/: dot only+ | Nslimit 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 Overlap -- ^ /Valid for/: G; /Default/: @'KeepOverlaps'@; /Parsing Default/: 'KeepOverlaps'; /Notes/: not dot | OverlapScaling Double -- ^ /Valid for/: G; /Default/: @-4@; /Minimum/: @-1.0e10@; /Notes/: prism only- | Pack Pack -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'DoPack'; /Notes/: not dot+ | Overlap Overlap -- ^ /Valid for/: G; /Default/: @'KeepOverlaps'@; /Parsing Default/: 'KeepOverlaps'; /Notes/: not dot | PackMode PackMode -- ^ /Valid for/: G; /Default/: @'PackNode'@; /Notes/: not dot+ | Pack Pack -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'DoPack'; /Notes/: not dot | Pad DPoint -- ^ /Valid for/: G; /Default/: @'DVal' 0.0555@ (4 points)- | Page Point -- ^ /Valid for/: G | PageDir PageDir -- ^ /Valid for/: G; /Default/: @'BL'@- | PenColor Color -- ^ /Valid for/: C; /Default/: @black@+ | Page Point -- ^ /Valid for/: G+ | PenColor Color -- ^ /Valid for/: C; /Default/: @X11Color 'Black'@ | PenWidth Double -- ^ /Valid for/: CNE; /Default/: @1.0@; /Minimum/: @0.0@ | Peripheries Int -- ^ /Valid for/: NC; /Default/: shape default (nodes), @1@ (clusters); /Minimum/: 0 | Pin Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: fdp, neato only | Pos Pos -- ^ /Valid for/: EN | QuadTree QuadType -- ^ /Valid for/: G; /Default/: @'NormalQT'@; /Parsing Default/: 'NormalQT'; /Notes/: sfdp only | Quantum Double -- ^ /Valid for/: G; /Default/: @0.0@; /Minimum/: @0.0@- | Rank RankType -- ^ /Valid for/: S; /Notes/: dot only | RankDir RankDir -- ^ /Valid for/: G; /Default/: @'TB'@; /Notes/: dot only- | Ranksep Double -- ^ /Valid for/: G; /Default/: @0.5@ (dot), @1.0@ (twopi); /Minimum/: 0.02; /Notes/: twopi, dot only+ | RankSep Double -- ^ /Valid for/: G; /Default/: @0.5@ (dot), @1.0@ (twopi); /Minimum/: 0.02; /Notes/: twopi, dot only+ | Rank RankType -- ^ /Valid for/: S; /Notes/: dot only | Ratio Ratios -- ^ /Valid for/: G | Rects Rect -- ^ /Valid for/: N; /Notes/: write only | Regular Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'@@ -301,8 +315,8 @@ | SamplePoints Int -- ^ /Valid for/: N; /Default/: @8@ (output), @20@ (overlap and image maps) | SearchSize Int -- ^ /Valid for/: G; /Default/: @30@; /Notes/: dot only | Sep DPoint -- ^ /Valid for/: G; /Default/: @+4@; /Notes/: not dot- | Shape Shape -- ^ /Valid for/: N; /Default/: @'Ellipse'@ | ShapeFile String -- ^ /Valid for/: N; /Default/: @\"\"@+ | Shape Shape -- ^ /Valid for/: N; /Default/: @'Ellipse'@ | 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@@ -311,8 +325,8 @@ | SortV Int -- ^ /Valid for/: GCN; /Default/: @0@; /Minimum/: @0@ | Splines EdgeType -- ^ /Valid for/: G; /Parsing Default/: 'SplineEdges' | Start StartType -- ^ /Valid for/: G; /Default/: @\"\"@; /Notes/: fdp, neato only- | Style [StyleItem] -- ^ /Valid for/: ENC | StyleSheet String -- ^ /Valid for/: G; /Default/: @\"\"@; /Notes/: svg only+ | Style [StyleItem] -- ^ /Valid for/: ENC | TailURL URL -- ^ /Valid for/: E; /Default/: @\"\"@; /Notes/: svg, map only | TailClip Bool -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True' | TailLabel Label -- ^ /Valid for/: E; /Default/: @\"\"@@@ -328,7 +342,7 @@ | 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, Show, Read)+ deriving (Eq, Ord, Show, Read) type Attributes = [Attribute] @@ -345,16 +359,16 @@ unqtDot (Center v) = printField "center" v unqtDot (Charset v) = printField "charset" v unqtDot (ClusterRank v) = printField "clusterrank" v- unqtDot (Color v) = printField "color" v unqtDot (ColorScheme v) = printField "colorscheme" v+ unqtDot (Color v) = printField "color" v unqtDot (Comment v) = printField "comment" v unqtDot (Compound v) = printField "compound" v unqtDot (Concentrate v) = printField "concentrate" v unqtDot (Constraint v) = printField "constraint" v unqtDot (Decorate v) = printField "decorate" v unqtDot (DefaultDist v) = printField "defaultdist" v- unqtDot (Dim v) = printField "dim" v unqtDot (Dimen v) = printField "dimen" v+ unqtDot (Dim v) = printField "dim" v unqtDot (Dir v) = printField "dir" v unqtDot (DirEdgeConstraints v) = printField "diredgeconstraints" v unqtDot (Distortion v) = printField "distortion" v@@ -382,7 +396,6 @@ unqtDot (ID v) = printField "id" v unqtDot (Image v) = printField "image" v unqtDot (ImageScale v) = printField "imagescale" v- unqtDot (Label v) = printField "label" v unqtDot (LabelURL v) = printField "labelURL" v unqtDot (LabelAngle v) = printField "labelangle" v unqtDot (LabelDistance v) = printField "labeldistance" v@@ -394,14 +407,15 @@ unqtDot (LabelLoc v) = printField "labelloc" v unqtDot (LabelTarget v) = printField "labeltarget" v unqtDot (LabelTooltip v) = printField "labeltooltip" v+ unqtDot (Label v) = printField "label" v unqtDot (Landscape v) = printField "landscape" v- unqtDot (Layer v) = printField "layer" v- unqtDot (Layers v) = printField "layers" v unqtDot (LayerSep v) = printField "layersep" v+ unqtDot (Layers v) = printField "layers" v+ unqtDot (Layer v) = printField "layer" v unqtDot (Layout v) = printField "layout" v unqtDot (Len v) = printField "len" v- unqtDot (Levels v) = printField "levels" v unqtDot (LevelsGap v) = printField "levelsgap" v+ unqtDot (Levels v) = printField "levels" v unqtDot (LHead v) = printField "lhead" v unqtDot (LPos v) = printField "lp" v unqtDot (LTail v) = printField "ltail" v@@ -410,25 +424,24 @@ unqtDot (MCLimit v) = printField "mclimit" v unqtDot (MinDist v) = printField "mindist" v unqtDot (MinLen v) = printField "minlen" v- unqtDot (Mode v) = printField "mode" v unqtDot (Model v) = printField "model" v+ unqtDot (Mode v) = printField "mode" v unqtDot (Mosek v) = printField "mosek" v unqtDot (NodeSep v) = printField "nodesep" v unqtDot (NoJustify v) = printField "nojustify" v unqtDot (Normalize v) = printField "normalize" v- unqtDot (Nslimit v) = printField "nslimit" v unqtDot (Nslimit1 v) = printField "nslimit1" v+ unqtDot (Nslimit v) = printField "nslimit" v unqtDot (Ordering v) = printField "ordering" v unqtDot (Orientation v) = printField "orientation" v- unqtDot (OrientationGraph v) = printField "orientation" v unqtDot (OutputOrder v) = printField "outputorder" v- unqtDot (Overlap v) = printField "overlap" v unqtDot (OverlapScaling v) = printField "overlap_scaling" v- unqtDot (Pack v) = printField "pack" v+ unqtDot (Overlap v) = printField "overlap" v unqtDot (PackMode v) = printField "packmode" v+ unqtDot (Pack v) = printField "pack" v unqtDot (Pad v) = printField "pad" v- unqtDot (Page v) = printField "page" v unqtDot (PageDir v) = printField "pagedir" v+ unqtDot (Page v) = printField "page" v unqtDot (PenColor v) = printField "pencolor" v unqtDot (PenWidth v) = printField "penwidth" v unqtDot (Peripheries v) = printField "peripheries" v@@ -436,9 +449,9 @@ unqtDot (Pos v) = printField "pos" v unqtDot (QuadTree v) = printField "quadtree" v unqtDot (Quantum v) = printField "quantum" v- unqtDot (Rank v) = printField "rank" v unqtDot (RankDir v) = printField "rankdir" v- unqtDot (Ranksep v) = printField "ranksep" v+ unqtDot (RankSep v) = printField "ranksep" v+ unqtDot (Rank v) = printField "rank" v unqtDot (Ratio v) = printField "ratio" v unqtDot (Rects v) = printField "rects" v unqtDot (Regular v) = printField "regular" v@@ -451,8 +464,8 @@ unqtDot (SamplePoints v) = printField "samplepoints" v unqtDot (SearchSize v) = printField "searchsize" v unqtDot (Sep v) = printField "sep" v- unqtDot (Shape v) = printField "shape" v unqtDot (ShapeFile v) = printField "shapefile" v+ unqtDot (Shape v) = printField "shape" v unqtDot (ShowBoxes v) = printField "showboxes" v unqtDot (Sides v) = printField "sides" v unqtDot (Size v) = printField "size" v@@ -461,8 +474,8 @@ unqtDot (SortV v) = printField "sortv" v unqtDot (Splines v) = printField "splines" v unqtDot (Start v) = printField "start" v- unqtDot (Style v) = printField "style" v unqtDot (StyleSheet v) = printField "stylesheet" v+ unqtDot (Style v) = printField "style" v unqtDot (TailURL v) = printField "tailURL" v unqtDot (TailClip v) = printField "tailclip" v unqtDot (TailLabel v) = printField "taillabel" v@@ -494,16 +507,16 @@ , liftM Center $ parseFieldBool "center" , liftM Charset $ parseField "charset" , liftM ClusterRank $ parseField "clusterrank"- , liftM Color $ parseField "color" , liftM ColorScheme $ parseField "colorscheme"+ , liftM Color $ parseField "color" , liftM Comment $ parseField "comment" , liftM Compound $ parseFieldBool "compound" , liftM Concentrate $ parseFieldBool "concentrate" , liftM Constraint $ parseFieldBool "constraint" , liftM Decorate $ parseFieldBool "decorate" , liftM DefaultDist $ parseField "defaultdist"- , liftM Dim $ parseField "dim" , liftM Dimen $ parseField "dimen"+ , liftM Dim $ parseField "dim" , liftM Dir $ parseField "dir" , liftM DirEdgeConstraints $ parseFieldDef EdgeConstraints "diredgeconstraints" , liftM Distortion $ parseField "distortion"@@ -531,7 +544,6 @@ , liftM ID $ parseField "id" , liftM Image $ parseField "image" , liftM ImageScale $ parseFieldDef UniformScale "imagescale"- , liftM Label $ parseField "label" , liftM LabelURL $ parseFields ["labelURL", "labelhref"] , liftM LabelAngle $ parseField "labelangle" , liftM LabelDistance $ parseField "labeldistance"@@ -543,14 +555,15 @@ , liftM LabelLoc $ parseField "labelloc" , liftM LabelTarget $ parseField "labeltarget" , liftM LabelTooltip $ parseField "labeltooltip"+ , liftM Label $ parseField "label" , liftM Landscape $ parseFieldBool "landscape"- , liftM Layer $ parseField "layer"- , liftM Layers $ parseField "layers" , liftM LayerSep $ parseField "layersep"+ , liftM Layers $ parseField "layers"+ , liftM Layer $ parseField "layer" , liftM Layout $ parseField "layout" , liftM Len $ parseField "len"- , liftM Levels $ parseField "levels" , liftM LevelsGap $ parseField "levelsgap"+ , liftM Levels $ parseField "levels" , liftM LHead $ parseField "lhead" , liftM LPos $ parseField "lp" , liftM LTail $ parseField "ltail"@@ -559,25 +572,24 @@ , liftM MCLimit $ parseField "mclimit" , liftM MinDist $ parseField "mindist" , liftM MinLen $ parseField "minlen"- , liftM Mode $ parseField "mode" , liftM Model $ parseField "model"+ , liftM Mode $ parseField "mode" , liftM Mosek $ parseFieldBool "mosek" , liftM NodeSep $ parseField "nodesep" , liftM NoJustify $ parseFieldBool "nojustify" , liftM Normalize $ parseFieldBool "normalize"- , liftM Nslimit $ parseField "nslimit" , liftM Nslimit1 $ parseField "nslimit1"+ , liftM Nslimit $ parseField "nslimit" , liftM Ordering $ parseField "ordering" , liftM Orientation $ parseField "orientation"- , liftM OrientationGraph $ parseField "orientation" , liftM OutputOrder $ parseField "outputorder"- , liftM Overlap $ parseFieldDef KeepOverlaps "overlap" , liftM OverlapScaling $ parseField "overlap_scaling"- , liftM Pack $ parseFieldDef DoPack "pack"+ , liftM Overlap $ parseFieldDef KeepOverlaps "overlap" , liftM PackMode $ parseField "packmode"+ , liftM Pack $ parseFieldDef DoPack "pack" , liftM Pad $ parseField "pad"- , liftM Page $ parseField "page" , liftM PageDir $ parseField "pagedir"+ , liftM Page $ parseField "page" , liftM PenColor $ parseField "pencolor" , liftM PenWidth $ parseField "penwidth" , liftM Peripheries $ parseField "peripheries"@@ -585,9 +597,9 @@ , liftM Pos $ parseField "pos" , liftM QuadTree $ parseFieldDef NormalQT "quadtree" , liftM Quantum $ parseField "quantum"- , liftM Rank $ parseField "rank" , liftM RankDir $ parseField "rankdir"- , liftM Ranksep $ parseField "ranksep"+ , liftM RankSep $ parseField "ranksep"+ , liftM Rank $ parseField "rank" , liftM Ratio $ parseField "ratio" , liftM Rects $ parseField "rects" , liftM Regular $ parseFieldBool "regular"@@ -600,8 +612,8 @@ , liftM SamplePoints $ parseField "samplepoints" , liftM SearchSize $ parseField "searchsize" , liftM Sep $ parseField "sep"- , liftM Shape $ parseField "shape" , liftM ShapeFile $ parseField "shapefile"+ , liftM Shape $ parseField "shape" , liftM ShowBoxes $ parseField "showboxes" , liftM Sides $ parseField "sides" , liftM Size $ parseField "size"@@ -610,8 +622,8 @@ , liftM SortV $ parseField "sortv" , liftM Splines $ parseFieldDef SplineEdges "splines" , liftM Start $ parseField "start"- , liftM Style $ parseField "style" , liftM StyleSheet $ parseField "stylesheet"+ , liftM Style $ parseField "style" , liftM TailURL $ parseFields ["tailURL", "tailhref"] , liftM TailClip $ parseFieldBool "tailclip" , liftM TailLabel $ parseField "taillabel"@@ -649,8 +661,8 @@ usedByGraphs Compound{} = True usedByGraphs Concentrate{} = True usedByGraphs DefaultDist{} = True-usedByGraphs Dim{} = True usedByGraphs Dimen{} = True+usedByGraphs Dim{} = True usedByGraphs DirEdgeConstraints{} = True usedByGraphs DPI{} = True usedByGraphs Epsilon{} = True@@ -661,42 +673,41 @@ usedByGraphs FontPath{} = True usedByGraphs FontSize{} = True usedByGraphs ID{} = True-usedByGraphs Label{} = True usedByGraphs LabelJust{} = True usedByGraphs LabelLoc{} = True+usedByGraphs Label{} = True usedByGraphs Landscape{} = True-usedByGraphs Layers{} = True usedByGraphs LayerSep{} = True+usedByGraphs Layers{} = True usedByGraphs Layout{} = True-usedByGraphs Levels{} = True usedByGraphs LevelsGap{} = True+usedByGraphs Levels{} = True usedByGraphs LPos{} = True usedByGraphs Margin{} = True usedByGraphs MaxIter{} = True usedByGraphs MCLimit{} = True usedByGraphs MinDist{} = True-usedByGraphs Mode{} = True usedByGraphs Model{} = True+usedByGraphs Mode{} = True usedByGraphs Mosek{} = True usedByGraphs NodeSep{} = True usedByGraphs NoJustify{} = True usedByGraphs Normalize{} = True-usedByGraphs Nslimit{} = True usedByGraphs Nslimit1{} = True+usedByGraphs Nslimit{} = True usedByGraphs Ordering{} = True-usedByGraphs OrientationGraph{} = True usedByGraphs OutputOrder{} = True-usedByGraphs Overlap{} = True usedByGraphs OverlapScaling{} = True-usedByGraphs Pack{} = True+usedByGraphs Overlap{} = True usedByGraphs PackMode{} = True+usedByGraphs Pack{} = True usedByGraphs Pad{} = True-usedByGraphs Page{} = True usedByGraphs PageDir{} = True+usedByGraphs Page{} = True usedByGraphs QuadTree{} = True usedByGraphs Quantum{} = True usedByGraphs RankDir{} = True-usedByGraphs Ranksep{} = True+usedByGraphs RankSep{} = True usedByGraphs Ratio{} = True usedByGraphs ReMinCross{} = True usedByGraphs RepulsiveForce{} = True@@ -722,15 +733,15 @@ usedByClusters K{} = True usedByClusters URL{} = True usedByClusters BgColor{} = True-usedByClusters Color{} = True usedByClusters ColorScheme{} = True+usedByClusters Color{} = True usedByClusters FillColor{} = True usedByClusters FontColor{} = True usedByClusters FontName{} = True usedByClusters FontSize{} = True-usedByClusters Label{} = True usedByClusters LabelJust{} = True usedByClusters LabelLoc{} = True+usedByClusters Label{} = True usedByClusters LPos{} = True usedByClusters NoJustify{} = True usedByClusters PenColor{} = True@@ -751,8 +762,8 @@ -- | Determine if this Attribute is valid for use with Nodes. usedByNodes :: Attribute -> Bool usedByNodes URL{} = True-usedByNodes Color{} = True usedByNodes ColorScheme{} = True+usedByNodes Color{} = True usedByNodes Comment{} = True usedByNodes Distortion{} = True usedByNodes FillColor{} = True@@ -765,8 +776,8 @@ usedByNodes ID{} = True usedByNodes Image{} = True usedByNodes ImageScale{} = True-usedByNodes Label{} = True usedByNodes LabelLoc{} = True+usedByNodes Label{} = True usedByNodes Layer{} = True usedByNodes Margin{} = True usedByNodes NoJustify{} = True@@ -779,8 +790,8 @@ usedByNodes Regular{} = True usedByNodes Root{} = True usedByNodes SamplePoints{} = True-usedByNodes Shape{} = True usedByNodes ShapeFile{} = True+usedByNodes Shape{} = True usedByNodes ShowBoxes{} = True usedByNodes Sides{} = True usedByNodes Skew{} = True@@ -799,8 +810,8 @@ usedByEdges ArrowHead{} = True usedByEdges ArrowSize{} = True usedByEdges ArrowTail{} = True-usedByEdges Color{} = True usedByEdges ColorScheme{} = True+usedByEdges Color{} = True usedByEdges Comment{} = True usedByEdges Constraint{} = True usedByEdges Decorate{} = True@@ -818,7 +829,6 @@ usedByEdges HeadTarget{} = True usedByEdges HeadTooltip{} = True usedByEdges ID{} = True-usedByEdges Label{} = True usedByEdges LabelURL{} = True usedByEdges LabelAngle{} = True usedByEdges LabelDistance{} = True@@ -828,6 +838,7 @@ usedByEdges LabelFontSize{} = True usedByEdges LabelTarget{} = True usedByEdges LabelTooltip{} = True+usedByEdges Label{} = True usedByEdges Layer{} = True usedByEdges Len{} = True usedByEdges LHead{} = True@@ -860,7 +871,7 @@ Some 'Attribute's (mainly label-like ones) take a 'String' argument that allows for extra escape codes. This library doesn't do any extra checks or special parsing for these escape codes, but usage- of 'EscString' rather than 'String' indicates that the GraphViz+ of 'EscString' rather than 'String' indicates that the Graphviz tools will recognise these extra escape codes for these 'Attribute's. @@ -892,8 +903,13 @@ -- ----------------------------------------------------------------------------- +-- | No checks are placed on the content of a 'URL' value; however,+-- you should ensure that it does not contain any \'@>@\' or \'@<@\'+-- characters; Graphviz might care about escaping other characters+-- properly, but for the purposes of this library the presence of+-- these characters will make it harder to parse URLs. newtype URL = UStr { urlString :: EscString }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot URL where unqtDot = wrap (char '<') (char '>')@@ -904,7 +920,7 @@ parseUnqt = liftM UStr $ bracket (character open) (character close)- (liftM return $ satisfy ((/=) close))+ (many1 $ satisfy ((/=) close)) where open = '<' close = '>'@@ -925,7 +941,7 @@ -- been defined below as a convenience. Parsing of the 5 -- backward-compatible special cases is also supported. newtype ArrowType = AType [(ArrowModifier, ArrowShape)]- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) box, crow, diamond, dotArrow, inv, noArrow, normal, tee, vee :: ArrowType oDot, invDot, invODot, oBox, oDiamond :: ArrowType@@ -984,7 +1000,7 @@ | Normal | Tee | Vee- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot ArrowShape where unqtDot Box = unqtDot "box"@@ -1013,7 +1029,7 @@ data ArrowModifier = ArrMod { arrowFill :: ArrowFill , arrowSide :: ArrowSide }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) -- | Apply no modifications to an 'ArrowShape'. noMods :: ArrowModifier@@ -1033,14 +1049,14 @@ data ArrowFill = OpenArrow | FilledArrow- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot ArrowFill where unqtDot OpenArrow = char 'o' unqtDot FilledArrow = empty instance ParseDot ArrowFill where- parseUnqt = liftM (bool OpenArrow FilledArrow . isJust)+ parseUnqt = liftM (bool FilledArrow OpenArrow . isJust) $ optional (character 'o') -- Not used individually@@ -1051,7 +1067,7 @@ data ArrowSide = LeftSide | RightSide | BothSides- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot ArrowSide where unqtDot LeftSide = char 'l'@@ -1063,7 +1079,7 @@ $ optional (oneOf $ map character ['l', 'r']) where getSideType = maybe BothSides- (bool LeftSide RightSide . (==) 'l')+ (bool RightSide LeftSide . (==) 'l') -- Not used individually parse = parseUnqt@@ -1072,7 +1088,7 @@ data AspectType = RatioOnly Double | RatioPassCount Double Int- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot AspectType where unqtDot (RatioOnly r) = unqtDot r@@ -1094,7 +1110,7 @@ -- ----------------------------------------------------------------------------- data Rect = Rect Point Point- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Rect where unqtDot (Rect p1 p2) = commaDel p1 p2@@ -1108,97 +1124,10 @@ -- ----------------------------------------------------------------------------- -data Color = RGB { red :: Word8- , green :: Word8- , blue :: Word8- }- | RGBA { red :: Word8- , green :: Word8- , blue :: Word8- , alpha :: Word8- }- | HSV { hue :: Double- , saturation :: Double- , value :: Double- }- | ColorName String- deriving (Eq, Show, Read)--instance PrintDot Color where- unqtDot (RGB r g b) = hexColor [r,g,b]- unqtDot (RGBA r g b a) = hexColor [r,g,b,a]- unqtDot (HSV h s v) = hcat . punctuate comma $ map unqtDot [h,s,v]- unqtDot (ColorName name) = unqtDot name-- toDot (ColorName name) = toDot name- toDot c = doubleQuotes $ unqtDot c-- unqtListToDot = hcat . punctuate colon . map unqtDot-- listToDot [ColorName nm] = toDot nm- listToDot cs = doubleQuotes $ unqtListToDot cs--hexColor :: [Word8] -> DotCode-hexColor = (<>) (char '#') . hcat . map word8Doc--word8Doc :: Word8 -> DotCode-word8Doc w = text $ padding ++ simple- 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 ParseDot Color where- parseUnqt = oneOf [ parseHexBased- , parseHSV- , liftM ColorName parse -- Should we check it- -- is a colour?- ]- where- parseHexBased- = do character '#'- 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--- parse = liftM ColorName stringBlock -- unquoted Color Name- `onFail`- quotedParse parseUnqt-- parseUnqtList = sepBy1 parseUnqt (character ':')-- parseList = liftM (return . ColorName) stringBlock -- unquoted single- -- ColorName- `onFail`- quotedParse parseUnqtList---- ------------------------------------------------------------------------------ data ClusterMode = Local | Global | NoCluster- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot ClusterMode where unqtDot Local = unqtDot "local"@@ -1216,7 +1145,7 @@ -- ----------------------------------------------------------------------------- data DirType = Forward | Back | Both | NoDir- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot DirType where unqtDot Forward = unqtDot "forward"@@ -1237,7 +1166,7 @@ data DEConstraints = EdgeConstraints | NoConstraints | HierConstraints- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot DEConstraints where unqtDot EdgeConstraints = unqtDot True@@ -1245,7 +1174,7 @@ unqtDot HierConstraints = text "hier" instance ParseDot DEConstraints where- parseUnqt = liftM (bool EdgeConstraints NoConstraints) parse+ parseUnqt = liftM (bool NoConstraints EdgeConstraints) parse `onFail` stringRep HierConstraints "hier" @@ -1254,7 +1183,7 @@ -- | Either a 'Double' or a 'Point'. data DPoint = DVal Double | PVal Point- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot DPoint where unqtDot (DVal d) = unqtDot d@@ -1264,13 +1193,13 @@ toDot (PVal p) = toDot p instance ParseDot DPoint where- parseUnqt = liftM DVal parseUnqt+ parseUnqt = liftM PVal parseUnqt `onFail`- liftM PVal parseUnqt+ liftM DVal parseUnqt - parse = liftM DVal parse+ parse = liftM PVal parse `onFail`- liftM PVal parse+ liftM DVal parse -- ----------------------------------------------------------------------------- @@ -1278,7 +1207,7 @@ | KK | Hier | IpSep- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot ModeType where unqtDot Major = text "major"@@ -1298,7 +1227,7 @@ data Model = ShortPath | SubSet | Circuit- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot Model where unqtDot ShortPath = text "shortpath"@@ -1315,7 +1244,7 @@ data Label = StrLabel EscString | URLLabel URL- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Label where unqtDot (StrLabel s) = unqtDot s@@ -1337,7 +1266,7 @@ data Point = Point Int Int | PointD Double Double- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Point where unqtDot (Point x y) = commaDel x y@@ -1379,7 +1308,7 @@ | CompressOverlap | VpscOverlap | IpsepOverlap -- ^ Only when @mode == 'IpSep'@- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Overlap where unqtDot KeepOverlaps = unqtDot True@@ -1394,8 +1323,8 @@ instance ParseDot Overlap where parseUnqt = oneOf [ stringRep KeepOverlaps "true" , stringRep RemoveOverlaps "false"- , stringRep ScaleOverlaps "scale" , stringRep ScaleXYOverlaps "scalexy"+ , stringRep ScaleOverlaps "scale" , string "prism" >> liftM PrismOverlap (optional parse) , stringRep CompressOverlap "compress" , stringRep VpscOverlap "vpsc"@@ -1406,7 +1335,7 @@ data LayerRange = LRID LayerID | LRS LayerID String LayerID- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot LayerRange where unqtDot (LRID lid) = unqtDot lid@@ -1416,21 +1345,21 @@ toDot lrs = doubleQuotes $ unqtDot lrs instance ParseDot LayerRange where- parseUnqt = liftM LRID parseUnqt- `onFail`- do id1 <- parseUnqt+ parseUnqt = do id1 <- parseUnqt s <- parseLayerSep id2 <- parseUnqt return $ LRS id1 s id2+ `onFail`+ liftM LRID parseUnqt - parse = liftM LRID parse- `onFail`- quotedParse ( do id1 <- parseUnqt++ parse = quotedParse ( do id1 <- parseUnqt s <- parseLayerSep id2 <- parseUnqt return $ LRS id1 s id2 )-+ `onFail`+ liftM LRID parse parseLayerSep :: Parse String parseLayerSep = many1 . oneOf@@ -1440,12 +1369,23 @@ defLayerSep = [' ', ':', '\t'] parseLayerName :: Parse String-parseLayerName = many1 $ satisfy (flip notElem defLayerSep)+parseLayerName = many1 . orQuote+ $ satisfy (liftM2 (&&) notLayerSep ((/=) quoteChar)) +parseLayerName' :: Parse String+parseLayerName' = stringBlock+ `onFail`+ quotedParse parseLayerName++notLayerSep :: Char -> Bool+notLayerSep = flip notElem defLayerSep++-- | You should not have any quote characters for the 'LRName' option,+-- as it won't be parseable. data LayerID = AllLayers | LRInt Int | LRName String- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot LayerID where unqtDot AllLayers = text "all"@@ -1457,27 +1397,33 @@ toDot li = unqtDot li instance ParseDot LayerID where- parseUnqt = oneOf [ stringRep AllLayers "all"- , liftM LRInt parseUnqt- , liftM LRName parseLayerName- ]+ parseUnqt = liftM checkLayerName parseLayerName -- tests for Int and All - parse = oneOf [ optionalQuoted $ stringRep AllLayers "all"- , liftM LRInt parse -- Has optionalQuoted in it- , quotedParse $ liftM LRName parseLayerName+ parse = oneOf [ liftM checkLayerName parseLayerName'+ , liftM LRInt parse -- Mainly for unquoted case. ] --- | The list represent (Separator, Name)+checkLayerName :: String -> LayerID+checkLayerName str = maybe checkAll LRInt $ stringToInt str+ where+ checkAll = if map toLower str == "all"+ then AllLayers+ else LRName str++-- | The list represent (Separator, Name). You should not have any+-- quote characters for any of the 'String's, since there are+-- parsing problems with them. data LayerList = LL String [(String, String)]- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot LayerList where- unqtDot (LL l1 ols) = unqtDot l1 <> hsep (map subLL ols)+ unqtDot (LL l1 ols) = unqtDot l1 <> hcat (map subLL ols) where subLL (s, l) = unqtDot s <> unqtDot l + toDot (LL l1 []) = toDot l1 -- Might not need quotes, but probably will.- toDot = doubleQuotes . unqtDot+ toDot ll = doubleQuotes $ unqtDot ll instance ParseDot LayerList where parseUnqt = do l1 <- parseLayerName@@ -1487,11 +1433,13 @@ return $ LL l1 ols parse = quotedParse parseUnqt+ `onFail`+ liftM (flip LL []) (parseLayerName' `onFail` numString) -- ----------------------------------------------------------------------------- data OutputMode = BreadthFirst | NodesFirst | EdgesFirst- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot OutputMode where unqtDot BreadthFirst = text "breadthfirst"@@ -1509,7 +1457,7 @@ data Pack = DoPack | DontPack | PackMargin Int -- ^ If non-negative, then packs; otherwise doesn't.- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Pack where unqtDot DoPack = unqtDot True@@ -1518,8 +1466,8 @@ instance ParseDot Pack where -- What happens if it parses 0? It's non-negative, but parses as False- parseUnqt = oneOf [ liftM (bool DoPack DontPack) parseUnqt- , liftM PackMargin parseUnqt+ parseUnqt = oneOf [ liftM PackMargin parseUnqt+ , liftM (bool DontPack DoPack) onlyBool ] -- -----------------------------------------------------------------------------@@ -1530,7 +1478,7 @@ | PackArray Bool Bool (Maybe Int) -- ^ Sort by cols, sort -- by user, number of -- rows/cols- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot PackMode where unqtDot PackNode = text "node"@@ -1556,7 +1504,7 @@ , stringRep PackGraph "graph" , do string "array" mcu <- optional $ do character '_'- many1 $ satisfy (not . isDigit)+ many1 $ satisfy isCU let c = hasCharacter mcu 'c' u = hasCharacter mcu 'u' mi <- optional parseUnqt@@ -1564,12 +1512,14 @@ ] where hasCharacter ms c = maybe False (elem c) ms+ -- Also checks and removes quote characters+ isCU = flip elem ['c', 'u'] -- ----------------------------------------------------------------------------- data Pos = PointPos Point | SplinePos [Spline]- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Pos where unqtDot (PointPos p) = unqtDot p@@ -1579,9 +1529,14 @@ toDot (SplinePos ss) = toDot ss instance ParseDot Pos where- parseUnqt = oneOf [ liftM PointPos parseUnqt- , liftM SplinePos parseUnqt- ]+ -- Have to be careful with this: if we try to parse points first,+ -- then a spline with no start and end points will erroneously get+ -- parsed as a point and then the parser will crash as it expects+ -- a closing quote character...+ parseUnqt = do splns <- parseUnqt+ case splns of+ [Spline Nothing Nothing [p]] -> return $ PointPos p+ _ -> return $ SplinePos splns parse = quotedParse parseUnqt @@ -1593,7 +1548,7 @@ | NoEdges | PolyLine | CompoundEdge -- ^ fdp only- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot EdgeType where unqtDot SplineEdges = toDot True@@ -1607,7 +1562,7 @@ instance ParseDot EdgeType where -- Can't parse NoEdges without quotes.- parseUnqt = oneOf [ liftM (bool SplineEdges LineEdges) parse+ parseUnqt = oneOf [ liftM (bool LineEdges SplineEdges) parse , stringRep SplineEdges "spline" , stringRep LineEdges "line" , stringRep PolyLine "polyline"@@ -1623,7 +1578,7 @@ -- | 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, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot PageDir where unqtDot Bl = text "BL"@@ -1651,20 +1606,20 @@ -- | 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, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Spline where unqtDot (Spline ms me ps) = addS . addE . hsep $ map unqtDot ps where- addP t = maybe id ((<>) . commaDel t)+ addP t = maybe id ((<+>) . commaDel t) addS = addP 's' ms addE = addP 'e' me toDot = doubleQuotes . unqtDot - unqtListToDot = hsep . punctuate semi . map unqtDot+ unqtListToDot = hcat . punctuate semi . map unqtDot listToDot = doubleQuotes . unqtListToDot @@ -1687,7 +1642,7 @@ data QuadType = NormalQT | FastQT | NoQT- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot QuadType where unqtDot NormalQT = text "normal"@@ -1701,7 +1656,7 @@ , stringRep FastQT "fast" , stringRep NoQT "none" , character '2' >> return FastQT -- weird bool- , liftM (bool NormalQT NoQT) parse+ , liftM (bool NoQT NormalQT) parse ] -- -----------------------------------------------------------------------------@@ -1710,7 +1665,7 @@ data Root = IsCentral -- ^ For Nodes only | NotCentral -- ^ For Nodes only | NodeName String -- ^ For Graphs only- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Root where unqtDot IsCentral = unqtDot True@@ -1721,10 +1676,14 @@ toDot r = unqtDot r instance ParseDot Root where- parseUnqt = liftM (bool IsCentral NotCentral) parse+ parseUnqt = liftM (bool NotCentral IsCentral) onlyBool `onFail`- liftM NodeName parse+ liftM NodeName parseUnqt + parse = optionalQuoted (liftM (bool NotCentral IsCentral) onlyBool)+ `onFail`+ liftM NodeName parse+ -- ----------------------------------------------------------------------------- data RankType = SameRank@@ -1732,7 +1691,7 @@ | SourceRank | MaxRank | SinkRank- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot RankType where unqtDot SameRank = text "same"@@ -1755,7 +1714,7 @@ | FromLeft | FromBottom | FromRight- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot RankDir where unqtDot FromTop = text "TB"@@ -1803,7 +1762,7 @@ | Folder | Box3D | Component- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot Shape where unqtDot BoxShape = text "box"@@ -1838,7 +1797,8 @@ unqtDot Component = text "component" instance ParseDot Shape where- parseUnqt = oneOf [ stringReps BoxShape ["box","rect","rectangle"]+ parseUnqt = oneOf [ stringRep Box3D "box3d" -- Parse this before "box"+ , stringReps BoxShape ["box","rectangle","rect"] , stringRep Polygon "polygon" , stringRep Ellipse "ellipse" , stringRep Circle "circle"@@ -1866,7 +1826,6 @@ , stringRep Note "note" , stringRep Tab "tab" , stringRep Folder "folder"- , stringRep Box3D "box3d" , stringRep Component "component" ] @@ -1879,7 +1838,7 @@ | RNG | Spring | TriangleSmooth- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot SmoothType where unqtDot NoSmooth = text "none"@@ -1902,11 +1861,10 @@ -- ----------------------------------------------------------------------------- --- | It is assumed that at least one of these is @Just{}@. data StartType = StartStyle STStyle | StartSeed Int | StartStyleSeed STStyle Int- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot StartType where unqtDot (StartStyle ss) = unqtDot ss@@ -1924,7 +1882,7 @@ data STStyle = RegularStyle | SelfStyle | RandomStyle- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot STStyle where unqtDot RegularStyle = text "regular"@@ -1940,7 +1898,7 @@ -- ----------------------------------------------------------------------------- data StyleItem = SItem StyleName [String]- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot StyleItem where unqtDot (SItem nm args)@@ -1964,21 +1922,24 @@ args <- tryParseList' parseArgs return $ SItem nm args where- parseArgs = bracketSep (character '(')- parseComma- (character ')')- parseStyleName - -- Ignore quotations for the DD case atm, since I'm not sure how- -- to deal with it.+ parse = quotedParse (liftM2 SItem parseUnqt parseArgs)+ `onFail`+ liftM (flip SItem []) parse parseUnqtList = sepBy1 parseUnqt parseComma - -- Might not necessarily need to be quoted if a singleton...- parseList = liftM return parse+ parseList = quotedParse parseUnqtList `onFail`- parseUnqtList+ -- Might not necessarily need to be quoted if a singleton...+ liftM return parse +parseArgs :: Parse [String]+parseArgs = bracketSep (character '(')+ parseComma+ (character ')')+ parseStyleName+ data StyleName = Dashed -- ^ Nodes and Edges | Dotted -- ^ Nodes and Edges | Solid -- ^ Nodes and Edges@@ -1988,46 +1949,54 @@ | Diagonals -- ^ Nodes only | Rounded -- ^ Nodes and Clusters | DD String -- ^ Device Dependent- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot StyleName where- unqtDot Filled = text "filled"- unqtDot Invisible = text "invis"- unqtDot Diagonals = text "diagonals"- unqtDot Rounded = text "rounded" unqtDot Dashed = text "dashed" unqtDot Dotted = text "dotted" unqtDot Solid = text "solid" unqtDot Bold = text "bold"+ unqtDot Invisible = text "invis"+ unqtDot Filled = text "filled"+ unqtDot Diagonals = text "diagonals"+ unqtDot Rounded = text "rounded" unqtDot (DD nm) = unqtDot nm toDot (DD nm) = toDot nm toDot sn = unqtDot sn instance ParseDot StyleName where- parseUnqt = oneOf [ stringRep Filled "filled"- , stringRep Invisible "invis"- , stringRep Diagonals "diagonals"- , stringRep Rounded "rounded"- , stringRep Dashed "dashed"- , stringRep Dotted "dotted"- , stringRep Solid "solid"- , stringRep Bold "bold"- , liftM DD parseStyleName- ]+ parseUnqt = liftM checkDD parseStyleName - -- Never used on its own, so not bothering with a separate parse- -- implementation (which is iffy due to the DD case).+ parse = liftM checkDD+ $ quotedParse parseStyleName+ `onFail`+ -- In case a singleton DD is at the end of an attribute list.+ do f <- orQuote $ noneOf [quoteChar, '(', ')', ',', ' ', ']']+ r <- many (orQuote $ noneOf [quoteChar, '(', ')', ',', ']'])+ return $ f:r +checkDD :: String -> StyleName+checkDD str = case map toLower str of+ "dashed" -> Dashed+ "dotted" -> Dotted+ "solid" -> Solid+ "bold" -> Bold+ "invis" -> Invisible+ "filled" -> Filled+ "diagonals" -> Diagonals+ "rounded" -> Rounded+ _ -> DD str+ parseStyleName :: Parse String-parseStyleName = do f <- noneOf ['(', ')', ',', ' ']- r <- many (noneOf ['(', ')', ','])+parseStyleName = do f <- orQuote $ noneOf [quoteChar, '(', ')', ',', ' ']+ r <- many (orQuote $ noneOf [quoteChar, '(', ')', ',']) return $ f:r -- ----------------------------------------------------------------------------- newtype PortPos = PP CompassPoint- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot PortPos where unqtDot (PP cp) = unqtDot cp@@ -2047,7 +2016,7 @@ | NorthWest | CenterPoint | NoCP- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot CompassPoint where unqtDot NorthEast = text "ne"@@ -2062,14 +2031,15 @@ unqtDot NoCP = text "_" instance ParseDot CompassPoint where- parseUnqt = oneOf [ stringRep North "n"- , stringRep NorthEast "ne"- , stringRep East "e"+ -- Have to take care of longer parsing values first.+ parseUnqt = oneOf [ stringRep NorthEast "ne"+ , stringRep NorthWest "nw"+ , stringRep North "n" , stringRep SouthEast "se"- , stringRep South "s" , stringRep SouthWest "sw"+ , stringRep South "s"+ , stringRep East "e" , stringRep West "w"- , stringRep NorthWest "nw" , stringRep CenterPoint "c" , stringRep NoCP "_" ]@@ -2081,7 +2051,7 @@ , zVal :: Double , focus :: Maybe FocusType }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot ViewPort where unqtDot vp = maybe vs ((<>) (vs <> comma) . unqtDot)@@ -2105,7 +2075,7 @@ data FocusType = XY Point | NodeFocus String- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot FocusType where unqtDot (XY p) = unqtDot p@@ -2117,14 +2087,18 @@ instance ParseDot FocusType where parseUnqt = liftM XY parseUnqt `onFail`- liftM NodeFocus stringBlock+ liftM NodeFocus parseUnqt + parse = liftM XY parse+ `onFail`+ liftM NodeFocus parse+ -- ----------------------------------------------------------------------------- data VerticalPlacement = VTop | VCenter -- ^ Only valid for Nodes. | VBottom- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot VerticalPlacement where unqtDot VTop = char 't'@@ -2144,7 +2118,7 @@ | FillWidth | FillHeight | FillBoth- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot ScaleType where unqtDot UniformScale = unqtDot True@@ -2166,7 +2140,7 @@ data Justification = JLeft | JRight | JCenter- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot Justification where unqtDot JLeft = char 'l'@@ -2186,7 +2160,7 @@ | CompressRatio | ExpandRatio | AutoRatio- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot Ratios where unqtDot (AspectRatio r) = unqtDot r
+ Data/GraphViz/Attributes/Colors.hs view
@@ -0,0 +1,2541 @@+{- |+ Module : Data.GraphViz.Attributes.Colors+ Description : Helper functions for converting to Dot format.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module defines the various colors, etc. for Graphviz. For+ information on colors in general, see:+ <http://graphviz.org/doc/info/attrs.html#k:color>+ For named colors, see:+ <http://graphviz.org/doc/info/colors.html>++ Note that the ColorBrewer Color Schemes (shortened to just+ \"Brewer\" for the rest of this module) are covered by the+ following license (also available in the LICENSE file of this+ library):+ <http://graphviz.org/doc/info/colors.html#brewer_license>++ When parsing and printing 'Color' values (more specifically, the+ Brewer color values), the actual 'ColorScheme' being used isn't+ taken into account. Also, the \"@\/foo\/bar@\" style of overriding+ the 'ColorScheme' being used isn't supported for parsing purposes+ (and will result in a parsing failure).+-}+module Data.GraphViz.Attributes.Colors+ ( -- * Color schemes.+ ColorScheme(..)+ , BrewerName(..)+ -- * Colors+ , Color(..)+ , X11Color(..)+ -- * Conversion to\/from @Colour@.+ , toColour+ , x11Colour+ , fromColour+ , fromAColour+ ) where++import Data.GraphViz.Types.Parsing+import Data.GraphViz.Types.Printing++import Data.Colour( AlphaColour, opaque, transparent, withOpacity+ , over, black, alphaChannel, darken)+import Data.Colour.SRGB(Colour, sRGB, sRGB24, toSRGB24)+import Data.Colour.RGBSpace(uncurryRGB)+import Data.Colour.RGBSpace.HSV(hsv)++import Data.Char(isHexDigit)+import Numeric(showHex, readHex)+import Data.Word(Word8)+import Control.Monad(liftM, liftM2)++-- -----------------------------------------------------------------------------++-- | This represents the color schemes that Graphviz accepts. As+-- mentioned above, these are /not/ used for actual parsing or+-- printing.+data ColorScheme = X11+ | BrewerScheme BrewerName Word8 -- ^ The value of the+ -- scheme number+ -- depends on+ -- the name.+ deriving (Eq, Ord, Show, Read)++instance PrintDot ColorScheme where+ unqtDot X11 = unqtDot "X11"+ unqtDot (BrewerScheme n l) = unqtDot n <> unqtDot l++instance ParseDot ColorScheme where+ parseUnqt = stringRep X11 "X11"+ `onFail`+ liftM2 BrewerScheme parseUnqt parseUnqt++-- | All of these have a minimum level value of @3@, with a maximum+-- of @9@ unless otherwise specified.+data BrewerName = Accent -- ^ Maximum of @8@.+ | Blues+ | Brbg -- ^ Maximum of @11@.+ | Bugn+ | Bupu+ | Dark2 -- ^ Maximum of @8@.+ | Gnbu+ | Greens+ | Greys+ | Oranges+ | Orrd+ | Paired -- ^ Maximum of @12@.+ | Pastel1+ | Pastel2 -- ^ Maximum of @8@.+ | Piyg -- ^ Maximum of @11@.+ | Prgn -- ^ Maximum of @11@.+ | Pubu+ | Pubugn+ | Puor -- ^ Maximum of @11@; note that the last two are listed+ -- after the @'Purd'@ values in the+ -- documentation.+ | Purd+ | Purples+ | Rdbu -- ^ Maximum of @11@; note that the last two are listed+ -- first.+ | Rdgy -- ^ Maximum of @11@; note that the last two are listed+ -- after the @'Rdpu'@ values in the+ -- documentation.+ | Rdpu+ | Rdylbu -- ^ Maximum of @11@.+ | Rdylgn -- ^ Maximum of @11@.+ | Reds+ | Set1+ | Set2 -- ^ Maximum of @8@.+ | Set3 -- ^ Maximum of @12@.+ | Spectral -- ^ Maximum of @11@.+ | Ylgn+ | Ylgnbu+ | Ylorbr+ | Ylorrd+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot BrewerName where+ unqtDot Accent = unqtDot "accent"+ unqtDot Blues = unqtDot "blues"+ unqtDot Brbg = unqtDot "brbg"+ unqtDot Bugn = unqtDot "bugn"+ unqtDot Bupu = unqtDot "bupu"+ unqtDot Dark2 = unqtDot "dark2"+ unqtDot Gnbu = unqtDot "gnbu"+ unqtDot Greens = unqtDot "greens"+ unqtDot Greys = unqtDot "greys"+ unqtDot Oranges = unqtDot "oranges"+ unqtDot Orrd = unqtDot "orrd"+ unqtDot Paired = unqtDot "paired"+ unqtDot Pastel1 = unqtDot "pastel1"+ unqtDot Pastel2 = unqtDot "pastel2"+ unqtDot Piyg = unqtDot "piyg"+ unqtDot Prgn = unqtDot "prgn"+ unqtDot Pubu = unqtDot "pubu"+ unqtDot Pubugn = unqtDot "pubugn"+ unqtDot Puor = unqtDot "puor"+ unqtDot Purd = unqtDot "purd"+ unqtDot Purples = unqtDot "purples"+ unqtDot Rdbu = unqtDot "rdbu"+ unqtDot Rdgy = unqtDot "rdgy"+ unqtDot Rdpu = unqtDot "rdpu"+ unqtDot Rdylbu = unqtDot "rdylbu"+ unqtDot Rdylgn = unqtDot "rdylgn"+ unqtDot Reds = unqtDot "reds"+ unqtDot Set1 = unqtDot "set1"+ unqtDot Set2 = unqtDot "set2"+ unqtDot Set3 = unqtDot "set3"+ unqtDot Spectral = unqtDot "spectral"+ unqtDot Ylgn = unqtDot "ylgn"+ unqtDot Ylgnbu = unqtDot "ylgnbu"+ unqtDot Ylorbr = unqtDot "ylorbr"+ unqtDot Ylorrd = unqtDot "ylorrd"++instance ParseDot BrewerName where+ -- The order is different from above to make sure longer names are+ -- parsed first.+ parseUnqt = oneOf [ stringRep Accent "accent"+ , stringRep Blues "blues"+ , stringRep Brbg "brbg"+ , stringRep Bugn "bugn"+ , stringRep Bupu "bupu"+ , stringRep Dark2 "dark2"+ , stringRep Gnbu "gnbu"+ , stringRep Greens "greens"+ , stringRep Greys "greys"+ , stringRep Oranges "oranges"+ , stringRep Orrd "orrd"+ , stringRep Paired "paired"+ , stringRep Pastel1 "pastel1"+ , stringRep Pastel2 "pastel2"+ , stringRep Piyg "piyg"+ , stringRep Prgn "prgn"+ , stringRep Pubugn "pubugn"+ , stringRep Pubu "pubu"+ , stringRep Puor "puor"+ , stringRep Purd "purd"+ , stringRep Purples "purples"+ , stringRep Rdbu "rdbu"+ , stringRep Rdgy "rdgy"+ , stringRep Rdpu "rdpu"+ , stringRep Rdylbu "rdylbu"+ , stringRep Rdylgn "rdylgn"+ , stringRep Reds "reds"+ , stringRep Set1 "set1"+ , stringRep Set2 "set2"+ , stringRep Set3 "set3"+ , stringRep Spectral "spectral"+ , stringRep Ylgnbu "ylgnbu"+ , stringRep Ylgn "ylgn"+ , stringRep Ylorbr "ylorbr"+ , stringRep Ylorrd "ylorrd"+ ]++-- -----------------------------------------------------------------------------++-- | Defining a color for use with Graphviz. Note that named colors+-- have been split up into 'X11Color's and those based upon the+-- Brewer color schemes.+data Color = RGB { red :: Word8+ , green :: Word8+ , blue :: Word8+ }+ | RGBA { red :: Word8+ , green :: Word8+ , blue :: Word8+ , alpha :: Word8+ }+ -- | The 'hue', 'saturation' and 'value' values must all+ -- be @0 <= x <=1@.+ | HSV { hue :: Double+ , saturation :: Double+ , value :: Double+ }+ | X11Color X11Color+ | BrewerColor Word8 -- ^ This value should be between @1@+ -- and the level of the 'BrewerName'+ -- being used.+ deriving (Eq, Ord, Show, Read)++instance PrintDot Color where+ unqtDot (RGB r g b) = hexColor [r,g,b]+ unqtDot (RGBA r g b a) = hexColor [r,g,b,a]+ unqtDot (HSV h s v) = hcat . punctuate comma $ map unqtDot [h,s,v]+ unqtDot (X11Color name) = unqtDot name+ unqtDot (BrewerColor n) = unqtDot n++ toDot (X11Color name) = toDot name+ toDot (BrewerColor n) = toDot n+ toDot c = doubleQuotes $ unqtDot c++ unqtListToDot = hcat . punctuate colon . map unqtDot++ -- These two don't need to be quoted if they're on their own.+ listToDot [X11Color name] = toDot name+ listToDot [BrewerColor n] = toDot n+ listToDot cs = doubleQuotes $ unqtListToDot cs++hexColor :: [Word8] -> DotCode+hexColor = (<>) (char '#') . hcat . map word8Doc++word8Doc :: Word8 -> DotCode+word8Doc w = text $ padding ++ simple+ 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 ParseDot Color where+ parseUnqt = oneOf [ parseHexBased+ , parseHSV+ , liftM X11Color parseUnqt+ , liftM BrewerColor parseUnqt+ ]+ where+ parseHexBased+ = do character '#'+ 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+++ parse = quotedParse parseUnqt+ `onFail` -- These two can be unquoted+ oneOf [ liftM X11Color parseUnqt+ , liftM BrewerColor parseUnqt+ ]++ parseUnqtList = sepBy1 parseUnqt (character ':')++ parseList = liftM return+ -- Unquoted single color+ (oneOf [ liftM X11Color parseUnqt+ , liftM BrewerColor parseUnqt+ ]+ )+ `onFail`+ quotedParse parseUnqtList++-- -----------------------------------------------------------------------------++-- | The X11 colors that Graphviz uses. Note that these are slightly+-- different from the \"normal\" X11 colors used (e.g. the inclusion+-- of @Crimson@). Graphviz's list of colors also duplicated almost+-- all @Gray@ colors with @Grey@ ones; parsing of an 'X11Color'+-- which is specified using \"grey\" will succeed, even for those+-- that don't have the duplicate spelling (e.g. @DarkSlateGray1@).+data X11Color = AliceBlue+ | AntiqueWhite+ | AntiqueWhite1+ | AntiqueWhite2+ | AntiqueWhite3+ | AntiqueWhite4+ | Aquamarine+ | Aquamarine1+ | Aquamarine2+ | Aquamarine3+ | Aquamarine4+ | Azure+ | Azure1+ | Azure2+ | Azure3+ | Azure4+ | Beige+ | Bisque+ | Bisque1+ | Bisque2+ | Bisque3+ | Bisque4+ | Black+ | BlanchedAlmond+ | Blue+ | Blue1+ | Blue2+ | Blue3+ | Blue4+ | BlueViolet+ | Brown+ | Brown1+ | Brown2+ | Brown3+ | Brown4+ | Burlywood+ | Burlywood1+ | Burlywood2+ | Burlywood3+ | Burlywood4+ | CadetBlue+ | CadetBlue1+ | CadetBlue2+ | CadetBlue3+ | CadetBlue4+ | Chartreuse+ | Chartreuse1+ | Chartreuse2+ | Chartreuse3+ | Chartreuse4+ | Chocolate+ | Chocolate1+ | Chocolate2+ | Chocolate3+ | Chocolate4+ | Coral+ | Coral1+ | Coral2+ | Coral3+ | Coral4+ | CornFlowerBlue+ | CornSilk+ | CornSilk1+ | CornSilk2+ | CornSilk3+ | CornSilk4+ | Crimson+ | Cyan+ | Cyan1+ | Cyan2+ | Cyan3+ | Cyan4+ | DarkGoldenrod+ | DarkGoldenrod1+ | DarkGoldenrod2+ | DarkGoldenrod3+ | DarkGoldenrod4+ | DarkGreen+ | Darkkhaki+ | DarkOliveGreen+ | DarkOliveGreen1+ | DarkOliveGreen2+ | DarkOliveGreen3+ | DarkOliveGreen4+ | DarkOrange+ | DarkOrange1+ | DarkOrange2+ | DarkOrange3+ | DarkOrange4+ | DarkOrchid+ | DarkOrchid1+ | DarkOrchid2+ | DarkOrchid3+ | DarkOrchid4+ | DarkSalmon+ | DarkSeaGreen+ | DarkSeaGreen1+ | DarkSeaGreen2+ | DarkSeaGreen3+ | DarkSeaGreen4+ | DarkSlateBlue+ | DarkSlateGray+ | DarkSlateGray1+ | DarkSlateGray2+ | DarkSlateGray3+ | DarkSlateGray4+ | DarkTurquoise+ | DarkViolet+ | DeepPink+ | DeepPink1+ | DeepPink2+ | DeepPink3+ | DeepPink4+ | DeepSkyBlue+ | DeepSkyBlue1+ | DeepSkyBlue2+ | DeepSkyBlue3+ | DeepSkyBlue4+ | DimGray+ | DodgerBlue+ | DodgerBlue1+ | DodgerBlue2+ | DodgerBlue3+ | DodgerBlue4+ | Firebrick+ | Firebrick1+ | Firebrick2+ | Firebrick3+ | Firebrick4+ | FloralWhite+ | ForestGreen+ | Gainsboro+ | GhostWhite+ | Gold+ | Gold1+ | Gold2+ | Gold3+ | Gold4+ | Goldenrod+ | Goldenrod1+ | Goldenrod2+ | Goldenrod3+ | Goldenrod4+ | Gray+ | Gray0+ | Gray1+ | Gray2+ | Gray3+ | Gray4+ | Gray5+ | Gray6+ | Gray7+ | Gray8+ | Gray9+ | Gray10+ | Gray11+ | Gray12+ | Gray13+ | Gray14+ | Gray15+ | Gray16+ | Gray17+ | Gray18+ | Gray19+ | Gray20+ | Gray21+ | Gray22+ | Gray23+ | Gray24+ | Gray25+ | Gray26+ | Gray27+ | Gray28+ | Gray29+ | Gray30+ | Gray31+ | Gray32+ | Gray33+ | Gray34+ | Gray35+ | Gray36+ | Gray37+ | Gray38+ | Gray39+ | Gray40+ | Gray41+ | Gray42+ | Gray43+ | Gray44+ | Gray45+ | Gray46+ | Gray47+ | Gray48+ | Gray49+ | Gray50+ | Gray51+ | Gray52+ | Gray53+ | Gray54+ | Gray55+ | Gray56+ | Gray57+ | Gray58+ | Gray59+ | Gray60+ | Gray61+ | Gray62+ | Gray63+ | Gray64+ | Gray65+ | Gray66+ | Gray67+ | Gray68+ | Gray69+ | Gray70+ | Gray71+ | Gray72+ | Gray73+ | Gray74+ | Gray75+ | Gray76+ | Gray77+ | Gray78+ | Gray79+ | Gray80+ | Gray81+ | Gray82+ | Gray83+ | Gray84+ | Gray85+ | Gray86+ | Gray87+ | Gray88+ | Gray89+ | Gray90+ | Gray91+ | Gray92+ | Gray93+ | Gray94+ | Gray95+ | Gray96+ | Gray97+ | Gray98+ | Gray99+ | Gray100+ | Green+ | Green1+ | Green2+ | Green3+ | Green4+ | GreenYellow+ | HoneyDew+ | HoneyDew1+ | HoneyDew2+ | HoneyDew3+ | HoneyDew4+ | HotPink+ | HotPink1+ | HotPink2+ | HotPink3+ | HotPink4+ | IndianRed+ | IndianRed1+ | IndianRed2+ | IndianRed3+ | IndianRed4+ | Indigo+ | Ivory+ | Ivory1+ | Ivory2+ | Ivory3+ | Ivory4+ | Khaki+ | Khaki1+ | Khaki2+ | Khaki3+ | Khaki4+ | Lavender+ | LavenderBlush+ | LavenderBlush1+ | LavenderBlush2+ | LavenderBlush3+ | LavenderBlush4+ | LawnGreen+ | LemonChiffon+ | LemonChiffon1+ | LemonChiffon2+ | LemonChiffon3+ | LemonChiffon4+ | LightBlue+ | LightBlue1+ | LightBlue2+ | LightBlue3+ | LightBlue4+ | LightCoral+ | LightCyan+ | LightCyan1+ | LightCyan2+ | LightCyan3+ | LightCyan4+ | LightGoldenrod+ | LightGoldenrod1+ | LightGoldenrod2+ | LightGoldenrod3+ | LightGoldenrod4+ | LightGoldenrodYellow+ | LightGray+ | LightPink+ | LightPink1+ | LightPink2+ | LightPink3+ | LightPink4+ | LightSalmon+ | LightSalmon1+ | LightSalmon2+ | LightSalmon3+ | LightSalmon4+ | LightSeaGreen+ | LightSkyBlue+ | LightSkyBlue1+ | LightSkyBlue2+ | LightSkyBlue3+ | LightSkyBlue4+ | LightSlateBlue+ | LightSlateGray+ | LightSteelBlue+ | LightSteelBlue1+ | LightSteelBlue2+ | LightSteelBlue3+ | LightSteelBlue4+ | LightYellow+ | LightYellow1+ | LightYellow2+ | LightYellow3+ | LightYellow4+ | LimeGreen+ | Linen+ | Magenta+ | Magenta1+ | Magenta2+ | Magenta3+ | Magenta4+ | Maroon+ | Maroon1+ | Maroon2+ | Maroon3+ | Maroon4+ | MediumAquamarine+ | MediumBlue+ | MediumOrchid+ | MediumOrchid1+ | MediumOrchid2+ | MediumOrchid3+ | MediumOrchid4+ | MediumPurple+ | MediumPurple1+ | MediumPurple2+ | MediumPurple3+ | MediumPurple4+ | MediumSeaGreen+ | MediumSlateBlue+ | MediumSpringGreen+ | MediumTurquoise+ | MediumVioletRed+ | MidnightBlue+ | MintCream+ | MistyRose+ | MistyRose1+ | MistyRose2+ | MistyRose3+ | MistyRose4+ | Moccasin+ | NavajoWhite+ | NavajoWhite1+ | NavajoWhite2+ | NavajoWhite3+ | NavajoWhite4+ | Navy+ | NavyBlue+ | OldLace+ | OliveDrab+ | OliveDrab1+ | OliveDrab2+ | OliveDrab3+ | OliveDrab4+ | Orange+ | Orange1+ | Orange2+ | Orange3+ | Orange4+ | OrangeRed+ | OrangeRed1+ | OrangeRed2+ | OrangeRed3+ | OrangeRed4+ | Orchid+ | Orchid1+ | Orchid2+ | Orchid3+ | Orchid4+ | PaleGoldenrod+ | PaleGreen+ | PaleGreen1+ | PaleGreen2+ | PaleGreen3+ | PaleGreen4+ | PaleTurquoise+ | PaleTurquoise1+ | PaleTurquoise2+ | PaleTurquoise3+ | PaleTurquoise4+ | PaleVioletRed+ | PaleVioletRed1+ | PaleVioletRed2+ | PaleVioletRed3+ | PaleVioletRed4+ | PapayaWhip+ | PeachPuff+ | PeachPuff1+ | PeachPuff2+ | PeachPuff3+ | PeachPuff4+ | Peru+ | Pink+ | Pink1+ | Pink2+ | Pink3+ | Pink4+ | Plum+ | Plum1+ | Plum2+ | Plum3+ | Plum4+ | PowderBlue+ | Purple+ | Purple1+ | Purple2+ | Purple3+ | Purple4+ | Red+ | Red1+ | Red2+ | Red3+ | Red4+ | RosyBrown+ | RosyBrown1+ | RosyBrown2+ | RosyBrown3+ | RosyBrown4+ | RoyalBlue+ | RoyalBlue1+ | RoyalBlue2+ | RoyalBlue3+ | RoyalBlue4+ | SaddleBrown+ | Salmon+ | Salmon1+ | Salmon2+ | Salmon3+ | Salmon4+ | SandyBrown+ | SeaGreen+ | SeaGreen1+ | SeaGreen2+ | SeaGreen3+ | SeaGreen4+ | SeaShell+ | SeaShell1+ | SeaShell2+ | SeaShell3+ | SeaShell4+ | Sienna+ | Sienna1+ | Sienna2+ | Sienna3+ | Sienna4+ | SkyBlue+ | SkyBlue1+ | SkyBlue2+ | SkyBlue3+ | SkyBlue4+ | SlateBlue+ | SlateBlue1+ | SlateBlue2+ | SlateBlue3+ | SlateBlue4+ | SlateGray+ | SlateGray1+ | SlateGray2+ | SlateGray3+ | SlateGray4+ | Snow+ | Snow1+ | Snow2+ | Snow3+ | Snow4+ | SpringGreen+ | SpringGreen1+ | SpringGreen2+ | SpringGreen3+ | SpringGreen4+ | SteelBlue+ | SteelBlue1+ | SteelBlue2+ | SteelBlue3+ | SteelBlue4+ | Tan+ | Tan1+ | Tan2+ | Tan3+ | Tan4+ | Thistle+ | Thistle1+ | Thistle2+ | Thistle3+ | Thistle4+ | Tomato+ | Tomato1+ | Tomato2+ | Tomato3+ | Tomato4+ | Transparent -- ^ Equivalent to setting @Style [SItem Invisible []]@.+ | Turquoise+ | Turquoise1+ | Turquoise2+ | Turquoise3+ | Turquoise4+ | Violet+ | VioletRed+ | VioletRed1+ | VioletRed2+ | VioletRed3+ | VioletRed4+ | Wheat+ | Wheat1+ | Wheat2+ | Wheat3+ | Wheat4+ | White+ | WhiteSmoke+ | Yellow+ | Yellow1+ | Yellow2+ | Yellow3+ | Yellow4+ | YellowGreen+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot X11Color where+ unqtDot AliceBlue = unqtDot "aliceblue"+ unqtDot AntiqueWhite = unqtDot "antiquewhite"+ unqtDot AntiqueWhite1 = unqtDot "antiquewhite1"+ unqtDot AntiqueWhite2 = unqtDot "antiquewhite2"+ unqtDot AntiqueWhite3 = unqtDot "antiquewhite3"+ unqtDot AntiqueWhite4 = unqtDot "antiquewhite4"+ unqtDot Aquamarine = unqtDot "aquamarine"+ unqtDot Aquamarine1 = unqtDot "aquamarine1"+ unqtDot Aquamarine2 = unqtDot "aquamarine2"+ unqtDot Aquamarine3 = unqtDot "aquamarine3"+ unqtDot Aquamarine4 = unqtDot "aquamarine4"+ unqtDot Azure = unqtDot "azure"+ unqtDot Azure1 = unqtDot "azure1"+ unqtDot Azure2 = unqtDot "azure2"+ unqtDot Azure3 = unqtDot "azure3"+ unqtDot Azure4 = unqtDot "azure4"+ unqtDot Beige = unqtDot "beige"+ unqtDot Bisque = unqtDot "bisque"+ unqtDot Bisque1 = unqtDot "bisque1"+ unqtDot Bisque2 = unqtDot "bisque2"+ unqtDot Bisque3 = unqtDot "bisque3"+ unqtDot Bisque4 = unqtDot "bisque4"+ unqtDot Black = unqtDot "black"+ unqtDot BlanchedAlmond = unqtDot "blanchedalmond"+ unqtDot Blue = unqtDot "blue"+ unqtDot Blue1 = unqtDot "blue1"+ unqtDot Blue2 = unqtDot "blue2"+ unqtDot Blue3 = unqtDot "blue3"+ unqtDot Blue4 = unqtDot "blue4"+ unqtDot BlueViolet = unqtDot "blueviolet"+ unqtDot Brown = unqtDot "brown"+ unqtDot Brown1 = unqtDot "brown1"+ unqtDot Brown2 = unqtDot "brown2"+ unqtDot Brown3 = unqtDot "brown3"+ unqtDot Brown4 = unqtDot "brown4"+ unqtDot Burlywood = unqtDot "burlywood"+ unqtDot Burlywood1 = unqtDot "burlywood1"+ unqtDot Burlywood2 = unqtDot "burlywood2"+ unqtDot Burlywood3 = unqtDot "burlywood3"+ unqtDot Burlywood4 = unqtDot "burlywood4"+ unqtDot CadetBlue = unqtDot "cadetblue"+ unqtDot CadetBlue1 = unqtDot "cadetblue1"+ unqtDot CadetBlue2 = unqtDot "cadetblue2"+ unqtDot CadetBlue3 = unqtDot "cadetblue3"+ unqtDot CadetBlue4 = unqtDot "cadetblue4"+ unqtDot Chartreuse = unqtDot "chartreuse"+ unqtDot Chartreuse1 = unqtDot "chartreuse1"+ unqtDot Chartreuse2 = unqtDot "chartreuse2"+ unqtDot Chartreuse3 = unqtDot "chartreuse3"+ unqtDot Chartreuse4 = unqtDot "chartreuse4"+ unqtDot Chocolate = unqtDot "chocolate"+ unqtDot Chocolate1 = unqtDot "chocolate1"+ unqtDot Chocolate2 = unqtDot "chocolate2"+ unqtDot Chocolate3 = unqtDot "chocolate3"+ unqtDot Chocolate4 = unqtDot "chocolate4"+ unqtDot Coral = unqtDot "coral"+ unqtDot Coral1 = unqtDot "coral1"+ unqtDot Coral2 = unqtDot "coral2"+ unqtDot Coral3 = unqtDot "coral3"+ unqtDot Coral4 = unqtDot "coral4"+ unqtDot CornFlowerBlue = unqtDot "cornflowerblue"+ unqtDot CornSilk = unqtDot "cornsilk"+ unqtDot CornSilk1 = unqtDot "cornsilk1"+ unqtDot CornSilk2 = unqtDot "cornsilk2"+ unqtDot CornSilk3 = unqtDot "cornsilk3"+ unqtDot CornSilk4 = unqtDot "cornsilk4"+ unqtDot Crimson = unqtDot "crimson"+ unqtDot Cyan = unqtDot "cyan"+ unqtDot Cyan1 = unqtDot "cyan1"+ unqtDot Cyan2 = unqtDot "cyan2"+ unqtDot Cyan3 = unqtDot "cyan3"+ unqtDot Cyan4 = unqtDot "cyan4"+ unqtDot DarkGoldenrod = unqtDot "darkgoldenrod"+ unqtDot DarkGoldenrod1 = unqtDot "darkgoldenrod1"+ unqtDot DarkGoldenrod2 = unqtDot "darkgoldenrod2"+ unqtDot DarkGoldenrod3 = unqtDot "darkgoldenrod3"+ unqtDot DarkGoldenrod4 = unqtDot "darkgoldenrod4"+ unqtDot DarkGreen = unqtDot "darkgreen"+ unqtDot Darkkhaki = unqtDot "darkkhaki"+ unqtDot DarkOliveGreen = unqtDot "darkolivegreen"+ unqtDot DarkOliveGreen1 = unqtDot "darkolivegreen1"+ unqtDot DarkOliveGreen2 = unqtDot "darkolivegreen2"+ unqtDot DarkOliveGreen3 = unqtDot "darkolivegreen3"+ unqtDot DarkOliveGreen4 = unqtDot "darkolivegreen4"+ unqtDot DarkOrange = unqtDot "darkorange"+ unqtDot DarkOrange1 = unqtDot "darkorange1"+ unqtDot DarkOrange2 = unqtDot "darkorange2"+ unqtDot DarkOrange3 = unqtDot "darkorange3"+ unqtDot DarkOrange4 = unqtDot "darkorange4"+ unqtDot DarkOrchid = unqtDot "darkorchid"+ unqtDot DarkOrchid1 = unqtDot "darkorchid1"+ unqtDot DarkOrchid2 = unqtDot "darkorchid2"+ unqtDot DarkOrchid3 = unqtDot "darkorchid3"+ unqtDot DarkOrchid4 = unqtDot "darkorchid4"+ unqtDot DarkSalmon = unqtDot "darksalmon"+ unqtDot DarkSeaGreen = unqtDot "darkseagreen"+ unqtDot DarkSeaGreen1 = unqtDot "darkseagreen1"+ unqtDot DarkSeaGreen2 = unqtDot "darkseagreen2"+ unqtDot DarkSeaGreen3 = unqtDot "darkseagreen3"+ unqtDot DarkSeaGreen4 = unqtDot "darkseagreen4"+ unqtDot DarkSlateBlue = unqtDot "darkslateblue"+ unqtDot DarkSlateGray = unqtDot "darkslategray"+ unqtDot DarkSlateGray1 = unqtDot "darkslategray1"+ unqtDot DarkSlateGray2 = unqtDot "darkslategray2"+ unqtDot DarkSlateGray3 = unqtDot "darkslategray3"+ unqtDot DarkSlateGray4 = unqtDot "darkslategray4"+ unqtDot DarkTurquoise = unqtDot "darkturquoise"+ unqtDot DarkViolet = unqtDot "darkviolet"+ unqtDot DeepPink = unqtDot "deeppink"+ unqtDot DeepPink1 = unqtDot "deeppink1"+ unqtDot DeepPink2 = unqtDot "deeppink2"+ unqtDot DeepPink3 = unqtDot "deeppink3"+ unqtDot DeepPink4 = unqtDot "deeppink4"+ unqtDot DeepSkyBlue = unqtDot "deepskyblue"+ unqtDot DeepSkyBlue1 = unqtDot "deepskyblue1"+ unqtDot DeepSkyBlue2 = unqtDot "deepskyblue2"+ unqtDot DeepSkyBlue3 = unqtDot "deepskyblue3"+ unqtDot DeepSkyBlue4 = unqtDot "deepskyblue4"+ unqtDot DimGray = unqtDot "dimgray"+ unqtDot DodgerBlue = unqtDot "dodgerblue"+ unqtDot DodgerBlue1 = unqtDot "dodgerblue1"+ unqtDot DodgerBlue2 = unqtDot "dodgerblue2"+ unqtDot DodgerBlue3 = unqtDot "dodgerblue3"+ unqtDot DodgerBlue4 = unqtDot "dodgerblue4"+ unqtDot Firebrick = unqtDot "firebrick"+ unqtDot Firebrick1 = unqtDot "firebrick1"+ unqtDot Firebrick2 = unqtDot "firebrick2"+ unqtDot Firebrick3 = unqtDot "firebrick3"+ unqtDot Firebrick4 = unqtDot "firebrick4"+ unqtDot FloralWhite = unqtDot "floralwhite"+ unqtDot ForestGreen = unqtDot "forestgreen"+ unqtDot Gainsboro = unqtDot "gainsboro"+ unqtDot GhostWhite = unqtDot "ghostwhite"+ unqtDot Gold = unqtDot "gold"+ unqtDot Gold1 = unqtDot "gold1"+ unqtDot Gold2 = unqtDot "gold2"+ unqtDot Gold3 = unqtDot "gold3"+ unqtDot Gold4 = unqtDot "gold4"+ unqtDot Goldenrod = unqtDot "goldenrod"+ unqtDot Goldenrod1 = unqtDot "goldenrod1"+ unqtDot Goldenrod2 = unqtDot "goldenrod2"+ unqtDot Goldenrod3 = unqtDot "goldenrod3"+ unqtDot Goldenrod4 = unqtDot "goldenrod4"+ unqtDot Gray = unqtDot "gray"+ unqtDot Gray0 = unqtDot "gray0"+ unqtDot Gray1 = unqtDot "gray1"+ unqtDot Gray2 = unqtDot "gray2"+ unqtDot Gray3 = unqtDot "gray3"+ unqtDot Gray4 = unqtDot "gray4"+ unqtDot Gray5 = unqtDot "gray5"+ unqtDot Gray6 = unqtDot "gray6"+ unqtDot Gray7 = unqtDot "gray7"+ unqtDot Gray8 = unqtDot "gray8"+ unqtDot Gray9 = unqtDot "gray9"+ unqtDot Gray10 = unqtDot "gray10"+ unqtDot Gray11 = unqtDot "gray11"+ unqtDot Gray12 = unqtDot "gray12"+ unqtDot Gray13 = unqtDot "gray13"+ unqtDot Gray14 = unqtDot "gray14"+ unqtDot Gray15 = unqtDot "gray15"+ unqtDot Gray16 = unqtDot "gray16"+ unqtDot Gray17 = unqtDot "gray17"+ unqtDot Gray18 = unqtDot "gray18"+ unqtDot Gray19 = unqtDot "gray19"+ unqtDot Gray20 = unqtDot "gray20"+ unqtDot Gray21 = unqtDot "gray21"+ unqtDot Gray22 = unqtDot "gray22"+ unqtDot Gray23 = unqtDot "gray23"+ unqtDot Gray24 = unqtDot "gray24"+ unqtDot Gray25 = unqtDot "gray25"+ unqtDot Gray26 = unqtDot "gray26"+ unqtDot Gray27 = unqtDot "gray27"+ unqtDot Gray28 = unqtDot "gray28"+ unqtDot Gray29 = unqtDot "gray29"+ unqtDot Gray30 = unqtDot "gray30"+ unqtDot Gray31 = unqtDot "gray31"+ unqtDot Gray32 = unqtDot "gray32"+ unqtDot Gray33 = unqtDot "gray33"+ unqtDot Gray34 = unqtDot "gray34"+ unqtDot Gray35 = unqtDot "gray35"+ unqtDot Gray36 = unqtDot "gray36"+ unqtDot Gray37 = unqtDot "gray37"+ unqtDot Gray38 = unqtDot "gray38"+ unqtDot Gray39 = unqtDot "gray39"+ unqtDot Gray40 = unqtDot "gray40"+ unqtDot Gray41 = unqtDot "gray41"+ unqtDot Gray42 = unqtDot "gray42"+ unqtDot Gray43 = unqtDot "gray43"+ unqtDot Gray44 = unqtDot "gray44"+ unqtDot Gray45 = unqtDot "gray45"+ unqtDot Gray46 = unqtDot "gray46"+ unqtDot Gray47 = unqtDot "gray47"+ unqtDot Gray48 = unqtDot "gray48"+ unqtDot Gray49 = unqtDot "gray49"+ unqtDot Gray50 = unqtDot "gray50"+ unqtDot Gray51 = unqtDot "gray51"+ unqtDot Gray52 = unqtDot "gray52"+ unqtDot Gray53 = unqtDot "gray53"+ unqtDot Gray54 = unqtDot "gray54"+ unqtDot Gray55 = unqtDot "gray55"+ unqtDot Gray56 = unqtDot "gray56"+ unqtDot Gray57 = unqtDot "gray57"+ unqtDot Gray58 = unqtDot "gray58"+ unqtDot Gray59 = unqtDot "gray59"+ unqtDot Gray60 = unqtDot "gray60"+ unqtDot Gray61 = unqtDot "gray61"+ unqtDot Gray62 = unqtDot "gray62"+ unqtDot Gray63 = unqtDot "gray63"+ unqtDot Gray64 = unqtDot "gray64"+ unqtDot Gray65 = unqtDot "gray65"+ unqtDot Gray66 = unqtDot "gray66"+ unqtDot Gray67 = unqtDot "gray67"+ unqtDot Gray68 = unqtDot "gray68"+ unqtDot Gray69 = unqtDot "gray69"+ unqtDot Gray70 = unqtDot "gray70"+ unqtDot Gray71 = unqtDot "gray71"+ unqtDot Gray72 = unqtDot "gray72"+ unqtDot Gray73 = unqtDot "gray73"+ unqtDot Gray74 = unqtDot "gray74"+ unqtDot Gray75 = unqtDot "gray75"+ unqtDot Gray76 = unqtDot "gray76"+ unqtDot Gray77 = unqtDot "gray77"+ unqtDot Gray78 = unqtDot "gray78"+ unqtDot Gray79 = unqtDot "gray79"+ unqtDot Gray80 = unqtDot "gray80"+ unqtDot Gray81 = unqtDot "gray81"+ unqtDot Gray82 = unqtDot "gray82"+ unqtDot Gray83 = unqtDot "gray83"+ unqtDot Gray84 = unqtDot "gray84"+ unqtDot Gray85 = unqtDot "gray85"+ unqtDot Gray86 = unqtDot "gray86"+ unqtDot Gray87 = unqtDot "gray87"+ unqtDot Gray88 = unqtDot "gray88"+ unqtDot Gray89 = unqtDot "gray89"+ unqtDot Gray90 = unqtDot "gray90"+ unqtDot Gray91 = unqtDot "gray91"+ unqtDot Gray92 = unqtDot "gray92"+ unqtDot Gray93 = unqtDot "gray93"+ unqtDot Gray94 = unqtDot "gray94"+ unqtDot Gray95 = unqtDot "gray95"+ unqtDot Gray96 = unqtDot "gray96"+ unqtDot Gray97 = unqtDot "gray97"+ unqtDot Gray98 = unqtDot "gray98"+ unqtDot Gray99 = unqtDot "gray99"+ unqtDot Gray100 = unqtDot "gray100"+ unqtDot Green = unqtDot "green"+ unqtDot Green1 = unqtDot "green1"+ unqtDot Green2 = unqtDot "green2"+ unqtDot Green3 = unqtDot "green3"+ unqtDot Green4 = unqtDot "green4"+ unqtDot GreenYellow = unqtDot "greenyellow"+ unqtDot HoneyDew = unqtDot "honeydew"+ unqtDot HoneyDew1 = unqtDot "honeydew1"+ unqtDot HoneyDew2 = unqtDot "honeydew2"+ unqtDot HoneyDew3 = unqtDot "honeydew3"+ unqtDot HoneyDew4 = unqtDot "honeydew4"+ unqtDot HotPink = unqtDot "hotpink"+ unqtDot HotPink1 = unqtDot "hotpink1"+ unqtDot HotPink2 = unqtDot "hotpink2"+ unqtDot HotPink3 = unqtDot "hotpink3"+ unqtDot HotPink4 = unqtDot "hotpink4"+ unqtDot IndianRed = unqtDot "indianred"+ unqtDot IndianRed1 = unqtDot "indianred1"+ unqtDot IndianRed2 = unqtDot "indianred2"+ unqtDot IndianRed3 = unqtDot "indianred3"+ unqtDot IndianRed4 = unqtDot "indianred4"+ unqtDot Indigo = unqtDot "indigo"+ unqtDot Ivory = unqtDot "ivory"+ unqtDot Ivory1 = unqtDot "ivory1"+ unqtDot Ivory2 = unqtDot "ivory2"+ unqtDot Ivory3 = unqtDot "ivory3"+ unqtDot Ivory4 = unqtDot "ivory4"+ unqtDot Khaki = unqtDot "khaki"+ unqtDot Khaki1 = unqtDot "khaki1"+ unqtDot Khaki2 = unqtDot "khaki2"+ unqtDot Khaki3 = unqtDot "khaki3"+ unqtDot Khaki4 = unqtDot "khaki4"+ unqtDot Lavender = unqtDot "lavender"+ unqtDot LavenderBlush = unqtDot "lavenderblush"+ unqtDot LavenderBlush1 = unqtDot "lavenderblush1"+ unqtDot LavenderBlush2 = unqtDot "lavenderblush2"+ unqtDot LavenderBlush3 = unqtDot "lavenderblush3"+ unqtDot LavenderBlush4 = unqtDot "lavenderblush4"+ unqtDot LawnGreen = unqtDot "lawngreen"+ unqtDot LemonChiffon = unqtDot "lemonchiffon"+ unqtDot LemonChiffon1 = unqtDot "lemonchiffon1"+ unqtDot LemonChiffon2 = unqtDot "lemonchiffon2"+ unqtDot LemonChiffon3 = unqtDot "lemonchiffon3"+ unqtDot LemonChiffon4 = unqtDot "lemonchiffon4"+ unqtDot LightBlue = unqtDot "lightblue"+ unqtDot LightBlue1 = unqtDot "lightblue1"+ unqtDot LightBlue2 = unqtDot "lightblue2"+ unqtDot LightBlue3 = unqtDot "lightblue3"+ unqtDot LightBlue4 = unqtDot "lightblue4"+ unqtDot LightCoral = unqtDot "lightcoral"+ unqtDot LightCyan = unqtDot "lightcyan"+ unqtDot LightCyan1 = unqtDot "lightcyan1"+ unqtDot LightCyan2 = unqtDot "lightcyan2"+ unqtDot LightCyan3 = unqtDot "lightcyan3"+ unqtDot LightCyan4 = unqtDot "lightcyan4"+ unqtDot LightGoldenrod = unqtDot "lightgoldenrod"+ unqtDot LightGoldenrod1 = unqtDot "lightgoldenrod1"+ unqtDot LightGoldenrod2 = unqtDot "lightgoldenrod2"+ unqtDot LightGoldenrod3 = unqtDot "lightgoldenrod3"+ unqtDot LightGoldenrod4 = unqtDot "lightgoldenrod4"+ unqtDot LightGoldenrodYellow = unqtDot "lightgoldenrodyellow"+ unqtDot LightGray = unqtDot "lightgray"+ unqtDot LightPink = unqtDot "lightpink"+ unqtDot LightPink1 = unqtDot "lightpink1"+ unqtDot LightPink2 = unqtDot "lightpink2"+ unqtDot LightPink3 = unqtDot "lightpink3"+ unqtDot LightPink4 = unqtDot "lightpink4"+ unqtDot LightSalmon = unqtDot "lightsalmon"+ unqtDot LightSalmon1 = unqtDot "lightsalmon1"+ unqtDot LightSalmon2 = unqtDot "lightsalmon2"+ unqtDot LightSalmon3 = unqtDot "lightsalmon3"+ unqtDot LightSalmon4 = unqtDot "lightsalmon4"+ unqtDot LightSeaGreen = unqtDot "lightseagreen"+ unqtDot LightSkyBlue = unqtDot "lightskyblue"+ unqtDot LightSkyBlue1 = unqtDot "lightskyblue1"+ unqtDot LightSkyBlue2 = unqtDot "lightskyblue2"+ unqtDot LightSkyBlue3 = unqtDot "lightskyblue3"+ unqtDot LightSkyBlue4 = unqtDot "lightskyblue4"+ unqtDot LightSlateBlue = unqtDot "lightslateblue"+ unqtDot LightSlateGray = unqtDot "lightslategray"+ unqtDot LightSteelBlue = unqtDot "lightsteelblue"+ unqtDot LightSteelBlue1 = unqtDot "lightsteelblue1"+ unqtDot LightSteelBlue2 = unqtDot "lightsteelblue2"+ unqtDot LightSteelBlue3 = unqtDot "lightsteelblue3"+ unqtDot LightSteelBlue4 = unqtDot "lightsteelblue4"+ unqtDot LightYellow = unqtDot "lightyellow"+ unqtDot LightYellow1 = unqtDot "lightyellow1"+ unqtDot LightYellow2 = unqtDot "lightyellow2"+ unqtDot LightYellow3 = unqtDot "lightyellow3"+ unqtDot LightYellow4 = unqtDot "lightyellow4"+ unqtDot LimeGreen = unqtDot "limegreen"+ unqtDot Linen = unqtDot "linen"+ unqtDot Magenta = unqtDot "magenta"+ unqtDot Magenta1 = unqtDot "magenta1"+ unqtDot Magenta2 = unqtDot "magenta2"+ unqtDot Magenta3 = unqtDot "magenta3"+ unqtDot Magenta4 = unqtDot "magenta4"+ unqtDot Maroon = unqtDot "maroon"+ unqtDot Maroon1 = unqtDot "maroon1"+ unqtDot Maroon2 = unqtDot "maroon2"+ unqtDot Maroon3 = unqtDot "maroon3"+ unqtDot Maroon4 = unqtDot "maroon4"+ unqtDot MediumAquamarine = unqtDot "mediumaquamarine"+ unqtDot MediumBlue = unqtDot "mediumblue"+ unqtDot MediumOrchid = unqtDot "mediumorchid"+ unqtDot MediumOrchid1 = unqtDot "mediumorchid1"+ unqtDot MediumOrchid2 = unqtDot "mediumorchid2"+ unqtDot MediumOrchid3 = unqtDot "mediumorchid3"+ unqtDot MediumOrchid4 = unqtDot "mediumorchid4"+ unqtDot MediumPurple = unqtDot "mediumpurple"+ unqtDot MediumPurple1 = unqtDot "mediumpurple1"+ unqtDot MediumPurple2 = unqtDot "mediumpurple2"+ unqtDot MediumPurple3 = unqtDot "mediumpurple3"+ unqtDot MediumPurple4 = unqtDot "mediumpurple4"+ unqtDot MediumSeaGreen = unqtDot "mediumseagreen"+ unqtDot MediumSlateBlue = unqtDot "mediumslateblue"+ unqtDot MediumSpringGreen = unqtDot "mediumspringgreen"+ unqtDot MediumTurquoise = unqtDot "mediumturquoise"+ unqtDot MediumVioletRed = unqtDot "mediumvioletred"+ unqtDot MidnightBlue = unqtDot "midnightblue"+ unqtDot MintCream = unqtDot "mintcream"+ unqtDot MistyRose = unqtDot "mistyrose"+ unqtDot MistyRose1 = unqtDot "mistyrose1"+ unqtDot MistyRose2 = unqtDot "mistyrose2"+ unqtDot MistyRose3 = unqtDot "mistyrose3"+ unqtDot MistyRose4 = unqtDot "mistyrose4"+ unqtDot Moccasin = unqtDot "moccasin"+ unqtDot NavajoWhite = unqtDot "navajowhite"+ unqtDot NavajoWhite1 = unqtDot "navajowhite1"+ unqtDot NavajoWhite2 = unqtDot "navajowhite2"+ unqtDot NavajoWhite3 = unqtDot "navajowhite3"+ unqtDot NavajoWhite4 = unqtDot "navajowhite4"+ unqtDot Navy = unqtDot "navy"+ unqtDot NavyBlue = unqtDot "navyblue"+ unqtDot OldLace = unqtDot "oldlace"+ unqtDot OliveDrab = unqtDot "olivedrab"+ unqtDot OliveDrab1 = unqtDot "olivedrab1"+ unqtDot OliveDrab2 = unqtDot "olivedrab2"+ unqtDot OliveDrab3 = unqtDot "olivedrab3"+ unqtDot OliveDrab4 = unqtDot "olivedrab4"+ unqtDot Orange = unqtDot "orange"+ unqtDot Orange1 = unqtDot "orange1"+ unqtDot Orange2 = unqtDot "orange2"+ unqtDot Orange3 = unqtDot "orange3"+ unqtDot Orange4 = unqtDot "orange4"+ unqtDot OrangeRed = unqtDot "orangered"+ unqtDot OrangeRed1 = unqtDot "orangered1"+ unqtDot OrangeRed2 = unqtDot "orangered2"+ unqtDot OrangeRed3 = unqtDot "orangered3"+ unqtDot OrangeRed4 = unqtDot "orangered4"+ unqtDot Orchid = unqtDot "orchid"+ unqtDot Orchid1 = unqtDot "orchid1"+ unqtDot Orchid2 = unqtDot "orchid2"+ unqtDot Orchid3 = unqtDot "orchid3"+ unqtDot Orchid4 = unqtDot "orchid4"+ unqtDot PaleGoldenrod = unqtDot "palegoldenrod"+ unqtDot PaleGreen = unqtDot "palegreen"+ unqtDot PaleGreen1 = unqtDot "palegreen1"+ unqtDot PaleGreen2 = unqtDot "palegreen2"+ unqtDot PaleGreen3 = unqtDot "palegreen3"+ unqtDot PaleGreen4 = unqtDot "palegreen4"+ unqtDot PaleTurquoise = unqtDot "paleturquoise"+ unqtDot PaleTurquoise1 = unqtDot "paleturquoise1"+ unqtDot PaleTurquoise2 = unqtDot "paleturquoise2"+ unqtDot PaleTurquoise3 = unqtDot "paleturquoise3"+ unqtDot PaleTurquoise4 = unqtDot "paleturquoise4"+ unqtDot PaleVioletRed = unqtDot "palevioletred"+ unqtDot PaleVioletRed1 = unqtDot "palevioletred1"+ unqtDot PaleVioletRed2 = unqtDot "palevioletred2"+ unqtDot PaleVioletRed3 = unqtDot "palevioletred3"+ unqtDot PaleVioletRed4 = unqtDot "palevioletred4"+ unqtDot PapayaWhip = unqtDot "papayawhip"+ unqtDot PeachPuff = unqtDot "peachpuff"+ unqtDot PeachPuff1 = unqtDot "peachpuff1"+ unqtDot PeachPuff2 = unqtDot "peachpuff2"+ unqtDot PeachPuff3 = unqtDot "peachpuff3"+ unqtDot PeachPuff4 = unqtDot "peachpuff4"+ unqtDot Peru = unqtDot "peru"+ unqtDot Pink = unqtDot "pink"+ unqtDot Pink1 = unqtDot "pink1"+ unqtDot Pink2 = unqtDot "pink2"+ unqtDot Pink3 = unqtDot "pink3"+ unqtDot Pink4 = unqtDot "pink4"+ unqtDot Plum = unqtDot "plum"+ unqtDot Plum1 = unqtDot "plum1"+ unqtDot Plum2 = unqtDot "plum2"+ unqtDot Plum3 = unqtDot "plum3"+ unqtDot Plum4 = unqtDot "plum4"+ unqtDot PowderBlue = unqtDot "powderblue"+ unqtDot Purple = unqtDot "purple"+ unqtDot Purple1 = unqtDot "purple1"+ unqtDot Purple2 = unqtDot "purple2"+ unqtDot Purple3 = unqtDot "purple3"+ unqtDot Purple4 = unqtDot "purple4"+ unqtDot Red = unqtDot "red"+ unqtDot Red1 = unqtDot "red1"+ unqtDot Red2 = unqtDot "red2"+ unqtDot Red3 = unqtDot "red3"+ unqtDot Red4 = unqtDot "red4"+ unqtDot RosyBrown = unqtDot "rosybrown"+ unqtDot RosyBrown1 = unqtDot "rosybrown1"+ unqtDot RosyBrown2 = unqtDot "rosybrown2"+ unqtDot RosyBrown3 = unqtDot "rosybrown3"+ unqtDot RosyBrown4 = unqtDot "rosybrown4"+ unqtDot RoyalBlue = unqtDot "royalblue"+ unqtDot RoyalBlue1 = unqtDot "royalblue1"+ unqtDot RoyalBlue2 = unqtDot "royalblue2"+ unqtDot RoyalBlue3 = unqtDot "royalblue3"+ unqtDot RoyalBlue4 = unqtDot "royalblue4"+ unqtDot SaddleBrown = unqtDot "saddlebrown"+ unqtDot Salmon = unqtDot "salmon"+ unqtDot Salmon1 = unqtDot "salmon1"+ unqtDot Salmon2 = unqtDot "salmon2"+ unqtDot Salmon3 = unqtDot "salmon3"+ unqtDot Salmon4 = unqtDot "salmon4"+ unqtDot SandyBrown = unqtDot "sandybrown"+ unqtDot SeaGreen = unqtDot "seagreen"+ unqtDot SeaGreen1 = unqtDot "seagreen1"+ unqtDot SeaGreen2 = unqtDot "seagreen2"+ unqtDot SeaGreen3 = unqtDot "seagreen3"+ unqtDot SeaGreen4 = unqtDot "seagreen4"+ unqtDot SeaShell = unqtDot "seashell"+ unqtDot SeaShell1 = unqtDot "seashell1"+ unqtDot SeaShell2 = unqtDot "seashell2"+ unqtDot SeaShell3 = unqtDot "seashell3"+ unqtDot SeaShell4 = unqtDot "seashell4"+ unqtDot Sienna = unqtDot "sienna"+ unqtDot Sienna1 = unqtDot "sienna1"+ unqtDot Sienna2 = unqtDot "sienna2"+ unqtDot Sienna3 = unqtDot "sienna3"+ unqtDot Sienna4 = unqtDot "sienna4"+ unqtDot SkyBlue = unqtDot "skyblue"+ unqtDot SkyBlue1 = unqtDot "skyblue1"+ unqtDot SkyBlue2 = unqtDot "skyblue2"+ unqtDot SkyBlue3 = unqtDot "skyblue3"+ unqtDot SkyBlue4 = unqtDot "skyblue4"+ unqtDot SlateBlue = unqtDot "slateblue"+ unqtDot SlateBlue1 = unqtDot "slateblue1"+ unqtDot SlateBlue2 = unqtDot "slateblue2"+ unqtDot SlateBlue3 = unqtDot "slateblue3"+ unqtDot SlateBlue4 = unqtDot "slateblue4"+ unqtDot SlateGray = unqtDot "slategray"+ unqtDot SlateGray1 = unqtDot "slategray1"+ unqtDot SlateGray2 = unqtDot "slategray2"+ unqtDot SlateGray3 = unqtDot "slategray3"+ unqtDot SlateGray4 = unqtDot "slategray4"+ unqtDot Snow = unqtDot "snow"+ unqtDot Snow1 = unqtDot "snow1"+ unqtDot Snow2 = unqtDot "snow2"+ unqtDot Snow3 = unqtDot "snow3"+ unqtDot Snow4 = unqtDot "snow4"+ unqtDot SpringGreen = unqtDot "springgreen"+ unqtDot SpringGreen1 = unqtDot "springgreen1"+ unqtDot SpringGreen2 = unqtDot "springgreen2"+ unqtDot SpringGreen3 = unqtDot "springgreen3"+ unqtDot SpringGreen4 = unqtDot "springgreen4"+ unqtDot SteelBlue = unqtDot "steelblue"+ unqtDot SteelBlue1 = unqtDot "steelblue1"+ unqtDot SteelBlue2 = unqtDot "steelblue2"+ unqtDot SteelBlue3 = unqtDot "steelblue3"+ unqtDot SteelBlue4 = unqtDot "steelblue4"+ unqtDot Tan = unqtDot "tan"+ unqtDot Tan1 = unqtDot "tan1"+ unqtDot Tan2 = unqtDot "tan2"+ unqtDot Tan3 = unqtDot "tan3"+ unqtDot Tan4 = unqtDot "tan4"+ unqtDot Thistle = unqtDot "thistle"+ unqtDot Thistle1 = unqtDot "thistle1"+ unqtDot Thistle2 = unqtDot "thistle2"+ unqtDot Thistle3 = unqtDot "thistle3"+ unqtDot Thistle4 = unqtDot "thistle4"+ unqtDot Tomato = unqtDot "tomato"+ unqtDot Tomato1 = unqtDot "tomato1"+ unqtDot Tomato2 = unqtDot "tomato2"+ unqtDot Tomato3 = unqtDot "tomato3"+ unqtDot Tomato4 = unqtDot "tomato4"+ unqtDot Transparent = unqtDot "transparent"+ unqtDot Turquoise = unqtDot "turquoise"+ unqtDot Turquoise1 = unqtDot "turquoise1"+ unqtDot Turquoise2 = unqtDot "turquoise2"+ unqtDot Turquoise3 = unqtDot "turquoise3"+ unqtDot Turquoise4 = unqtDot "turquoise4"+ unqtDot Violet = unqtDot "violet"+ unqtDot VioletRed = unqtDot "violetred"+ unqtDot VioletRed1 = unqtDot "violetred1"+ unqtDot VioletRed2 = unqtDot "violetred2"+ unqtDot VioletRed3 = unqtDot "violetred3"+ unqtDot VioletRed4 = unqtDot "violetred4"+ unqtDot Wheat = unqtDot "wheat"+ unqtDot Wheat1 = unqtDot "wheat1"+ unqtDot Wheat2 = unqtDot "wheat2"+ unqtDot Wheat3 = unqtDot "wheat3"+ unqtDot Wheat4 = unqtDot "wheat4"+ unqtDot White = unqtDot "white"+ unqtDot WhiteSmoke = unqtDot "whitesmoke"+ unqtDot Yellow = unqtDot "yellow"+ unqtDot Yellow1 = unqtDot "yellow1"+ unqtDot Yellow2 = unqtDot "yellow2"+ unqtDot Yellow3 = unqtDot "yellow3"+ unqtDot Yellow4 = unqtDot "yellow4"+ unqtDot YellowGreen = unqtDot "yellowgreen"++instance ParseDot X11Color where+ parseUnqt = oneOf+ $ reverse [ stringRep AliceBlue "aliceblue"+ , stringRep AntiqueWhite "antiquewhite"+ , stringRep AntiqueWhite1 "antiquewhite1"+ , stringRep AntiqueWhite2 "antiquewhite2"+ , stringRep AntiqueWhite3 "antiquewhite3"+ , stringRep AntiqueWhite4 "antiquewhite4"+ , stringRep Aquamarine "aquamarine"+ , stringRep Aquamarine1 "aquamarine1"+ , stringRep Aquamarine2 "aquamarine2"+ , stringRep Aquamarine3 "aquamarine3"+ , stringRep Aquamarine4 "aquamarine4"+ , stringRep Azure "azure"+ , stringRep Azure1 "azure1"+ , stringRep Azure2 "azure2"+ , stringRep Azure3 "azure3"+ , stringRep Azure4 "azure4"+ , stringRep Beige "beige"+ , stringRep Bisque "bisque"+ , stringRep Bisque1 "bisque1"+ , stringRep Bisque2 "bisque2"+ , stringRep Bisque3 "bisque3"+ , stringRep Bisque4 "bisque4"+ , stringRep Black "black"+ , stringRep BlanchedAlmond "blanchedalmond"+ , stringRep Blue "blue"+ , stringRep Blue1 "blue1"+ , stringRep Blue2 "blue2"+ , stringRep Blue3 "blue3"+ , stringRep Blue4 "blue4"+ , stringRep BlueViolet "blueviolet"+ , stringRep Brown "brown"+ , stringRep Brown1 "brown1"+ , stringRep Brown2 "brown2"+ , stringRep Brown3 "brown3"+ , stringRep Brown4 "brown4"+ , stringRep Burlywood "burlywood"+ , stringRep Burlywood1 "burlywood1"+ , stringRep Burlywood2 "burlywood2"+ , stringRep Burlywood3 "burlywood3"+ , stringRep Burlywood4 "burlywood4"+ , stringRep CadetBlue "cadetblue"+ , stringRep CadetBlue1 "cadetblue1"+ , stringRep CadetBlue2 "cadetblue2"+ , stringRep CadetBlue3 "cadetblue3"+ , stringRep CadetBlue4 "cadetblue4"+ , stringRep Chartreuse "chartreuse"+ , stringRep Chartreuse1 "chartreuse1"+ , stringRep Chartreuse2 "chartreuse2"+ , stringRep Chartreuse3 "chartreuse3"+ , stringRep Chartreuse4 "chartreuse4"+ , stringRep Chocolate "chocolate"+ , stringRep Chocolate1 "chocolate1"+ , stringRep Chocolate2 "chocolate2"+ , stringRep Chocolate3 "chocolate3"+ , stringRep Chocolate4 "chocolate4"+ , stringRep Coral "coral"+ , stringRep Coral1 "coral1"+ , stringRep Coral2 "coral2"+ , stringRep Coral3 "coral3"+ , stringRep Coral4 "coral4"+ , stringRep CornFlowerBlue "cornflowerblue"+ , stringRep CornSilk "cornsilk"+ , stringRep CornSilk1 "cornsilk1"+ , stringRep CornSilk2 "cornsilk2"+ , stringRep CornSilk3 "cornsilk3"+ , stringRep CornSilk4 "cornsilk4"+ , stringRep Crimson "crimson"+ , stringRep Cyan "cyan"+ , stringRep Cyan1 "cyan1"+ , stringRep Cyan2 "cyan2"+ , stringRep Cyan3 "cyan3"+ , stringRep Cyan4 "cyan4"+ , stringRep DarkGoldenrod "darkgoldenrod"+ , stringRep DarkGoldenrod1 "darkgoldenrod1"+ , stringRep DarkGoldenrod2 "darkgoldenrod2"+ , stringRep DarkGoldenrod3 "darkgoldenrod3"+ , stringRep DarkGoldenrod4 "darkgoldenrod4"+ , stringRep DarkGreen "darkgreen"+ , stringRep Darkkhaki "darkkhaki"+ , stringRep DarkOliveGreen "darkolivegreen"+ , stringRep DarkOliveGreen1 "darkolivegreen1"+ , stringRep DarkOliveGreen2 "darkolivegreen2"+ , stringRep DarkOliveGreen3 "darkolivegreen3"+ , stringRep DarkOliveGreen4 "darkolivegreen4"+ , stringRep DarkOrange "darkorange"+ , stringRep DarkOrange1 "darkorange1"+ , stringRep DarkOrange2 "darkorange2"+ , stringRep DarkOrange3 "darkorange3"+ , stringRep DarkOrange4 "darkorange4"+ , stringRep DarkOrchid "darkorchid"+ , stringRep DarkOrchid1 "darkorchid1"+ , stringRep DarkOrchid2 "darkorchid2"+ , stringRep DarkOrchid3 "darkorchid3"+ , stringRep DarkOrchid4 "darkorchid4"+ , stringRep DarkSalmon "darksalmon"+ , stringRep DarkSeaGreen "darkseagreen"+ , stringRep DarkSeaGreen1 "darkseagreen1"+ , stringRep DarkSeaGreen2 "darkseagreen2"+ , stringRep DarkSeaGreen3 "darkseagreen3"+ , stringRep DarkSeaGreen4 "darkseagreen4"+ , stringRep DarkSlateBlue "darkslateblue"+ , stringReps DarkSlateGray ["darkslategray", "darkslategrey"]+ , stringReps DarkSlateGray1 ["darkslategray1", "darkslategrey1"]+ , stringReps DarkSlateGray2 ["darkslategray2", "darkslategrey2"]+ , stringReps DarkSlateGray3 ["darkslategray3", "darkslategrey3"]+ , stringReps DarkSlateGray4 ["darkslategray4", "darkslategrey4"]+ , stringRep DarkTurquoise "darkturquoise"+ , stringRep DarkViolet "darkviolet"+ , stringRep DeepPink "deeppink"+ , stringRep DeepPink1 "deeppink1"+ , stringRep DeepPink2 "deeppink2"+ , stringRep DeepPink3 "deeppink3"+ , stringRep DeepPink4 "deeppink4"+ , stringRep DeepSkyBlue "deepskyblue"+ , stringRep DeepSkyBlue1 "deepskyblue1"+ , stringRep DeepSkyBlue2 "deepskyblue2"+ , stringRep DeepSkyBlue3 "deepskyblue3"+ , stringRep DeepSkyBlue4 "deepskyblue4"+ , stringReps DimGray ["dimgray", "dimgrey"]+ , stringRep DodgerBlue "dodgerblue"+ , stringRep DodgerBlue1 "dodgerblue1"+ , stringRep DodgerBlue2 "dodgerblue2"+ , stringRep DodgerBlue3 "dodgerblue3"+ , stringRep DodgerBlue4 "dodgerblue4"+ , stringRep Firebrick "firebrick"+ , stringRep Firebrick1 "firebrick1"+ , stringRep Firebrick2 "firebrick2"+ , stringRep Firebrick3 "firebrick3"+ , stringRep Firebrick4 "firebrick4"+ , stringRep FloralWhite "floralwhite"+ , stringRep ForestGreen "forestgreen"+ , stringRep Gainsboro "gainsboro"+ , stringRep GhostWhite "ghostwhite"+ , stringRep Gold "gold"+ , stringRep Gold1 "gold1"+ , stringRep Gold2 "gold2"+ , stringRep Gold3 "gold3"+ , stringRep Gold4 "gold4"+ , stringRep Goldenrod "goldenrod"+ , stringRep Goldenrod1 "goldenrod1"+ , stringRep Goldenrod2 "goldenrod2"+ , stringRep Goldenrod3 "goldenrod3"+ , stringRep Goldenrod4 "goldenrod4"+ , stringReps Gray ["gray", "grey"]+ , stringReps Gray0 ["gray0", "grey0"]+ , stringReps Gray1 ["gray1", "grey1"]+ , stringReps Gray2 ["gray2", "grey2"]+ , stringReps Gray3 ["gray3", "grey3"]+ , stringReps Gray4 ["gray4", "grey4"]+ , stringReps Gray5 ["gray5", "grey5"]+ , stringReps Gray6 ["gray6", "grey6"]+ , stringReps Gray7 ["gray7", "grey7"]+ , stringReps Gray8 ["gray8", "grey8"]+ , stringReps Gray9 ["gray9", "grey9"]+ , stringReps Gray10 ["gray10", "grey10"]+ , stringReps Gray11 ["gray11", "grey11"]+ , stringReps Gray12 ["gray12", "grey12"]+ , stringReps Gray13 ["gray13", "grey13"]+ , stringReps Gray14 ["gray14", "grey14"]+ , stringReps Gray15 ["gray15", "grey15"]+ , stringReps Gray16 ["gray16", "grey16"]+ , stringReps Gray17 ["gray17", "grey17"]+ , stringReps Gray18 ["gray18", "grey18"]+ , stringReps Gray19 ["gray19", "grey19"]+ , stringReps Gray20 ["gray20", "grey20"]+ , stringReps Gray21 ["gray21", "grey21"]+ , stringReps Gray22 ["gray22", "grey22"]+ , stringReps Gray23 ["gray23", "grey23"]+ , stringReps Gray24 ["gray24", "grey24"]+ , stringReps Gray25 ["gray25", "grey25"]+ , stringReps Gray26 ["gray26", "grey26"]+ , stringReps Gray27 ["gray27", "grey27"]+ , stringReps Gray28 ["gray28", "grey28"]+ , stringReps Gray29 ["gray29", "grey29"]+ , stringReps Gray30 ["gray30", "grey30"]+ , stringReps Gray31 ["gray31", "grey31"]+ , stringReps Gray32 ["gray32", "grey32"]+ , stringReps Gray33 ["gray33", "grey33"]+ , stringReps Gray34 ["gray34", "grey34"]+ , stringReps Gray35 ["gray35", "grey35"]+ , stringReps Gray36 ["gray36", "grey36"]+ , stringReps Gray37 ["gray37", "grey37"]+ , stringReps Gray38 ["gray38", "grey38"]+ , stringReps Gray39 ["gray39", "grey39"]+ , stringReps Gray40 ["gray40", "grey40"]+ , stringReps Gray41 ["gray41", "grey41"]+ , stringReps Gray42 ["gray42", "grey42"]+ , stringReps Gray43 ["gray43", "grey43"]+ , stringReps Gray44 ["gray44", "grey44"]+ , stringReps Gray45 ["gray45", "grey45"]+ , stringReps Gray46 ["gray46", "grey46"]+ , stringReps Gray47 ["gray47", "grey47"]+ , stringReps Gray48 ["gray48", "grey48"]+ , stringReps Gray49 ["gray49", "grey49"]+ , stringReps Gray50 ["gray50", "grey50"]+ , stringReps Gray51 ["gray51", "grey51"]+ , stringReps Gray52 ["gray52", "grey52"]+ , stringReps Gray53 ["gray53", "grey53"]+ , stringReps Gray54 ["gray54", "grey54"]+ , stringReps Gray55 ["gray55", "grey55"]+ , stringReps Gray56 ["gray56", "grey56"]+ , stringReps Gray57 ["gray57", "grey57"]+ , stringReps Gray58 ["gray58", "grey58"]+ , stringReps Gray59 ["gray59", "grey59"]+ , stringReps Gray60 ["gray60", "grey60"]+ , stringReps Gray61 ["gray61", "grey61"]+ , stringReps Gray62 ["gray62", "grey62"]+ , stringReps Gray63 ["gray63", "grey63"]+ , stringReps Gray64 ["gray64", "grey64"]+ , stringReps Gray65 ["gray65", "grey65"]+ , stringReps Gray66 ["gray66", "grey66"]+ , stringReps Gray67 ["gray67", "grey67"]+ , stringReps Gray68 ["gray68", "grey68"]+ , stringReps Gray69 ["gray69", "grey69"]+ , stringReps Gray70 ["gray70", "grey70"]+ , stringReps Gray71 ["gray71", "grey71"]+ , stringReps Gray72 ["gray72", "grey72"]+ , stringReps Gray73 ["gray73", "grey73"]+ , stringReps Gray74 ["gray74", "grey74"]+ , stringReps Gray75 ["gray75", "grey75"]+ , stringReps Gray76 ["gray76", "grey76"]+ , stringReps Gray77 ["gray77", "grey77"]+ , stringReps Gray78 ["gray78", "grey78"]+ , stringReps Gray79 ["gray79", "grey79"]+ , stringReps Gray80 ["gray80", "grey80"]+ , stringReps Gray81 ["gray81", "grey81"]+ , stringReps Gray82 ["gray82", "grey82"]+ , stringReps Gray83 ["gray83", "grey83"]+ , stringReps Gray84 ["gray84", "grey84"]+ , stringReps Gray85 ["gray85", "grey85"]+ , stringReps Gray86 ["gray86", "grey86"]+ , stringReps Gray87 ["gray87", "grey87"]+ , stringReps Gray88 ["gray88", "grey88"]+ , stringReps Gray89 ["gray89", "grey89"]+ , stringReps Gray90 ["gray90", "grey90"]+ , stringReps Gray91 ["gray91", "grey91"]+ , stringReps Gray92 ["gray92", "grey92"]+ , stringReps Gray93 ["gray93", "grey93"]+ , stringReps Gray94 ["gray94", "grey94"]+ , stringReps Gray95 ["gray95", "grey95"]+ , stringReps Gray96 ["gray96", "grey96"]+ , stringReps Gray97 ["gray97", "grey97"]+ , stringReps Gray98 ["gray98", "grey98"]+ , stringReps Gray99 ["gray99", "grey99"]+ , stringReps Gray100 ["gray100", "grey100"]+ , stringRep Green "green"+ , stringRep Green1 "green1"+ , stringRep Green2 "green2"+ , stringRep Green3 "green3"+ , stringRep Green4 "green4"+ , stringRep GreenYellow "greenyellow"+ , stringRep HoneyDew "honeydew"+ , stringRep HoneyDew1 "honeydew1"+ , stringRep HoneyDew2 "honeydew2"+ , stringRep HoneyDew3 "honeydew3"+ , stringRep HoneyDew4 "honeydew4"+ , stringRep HotPink "hotpink"+ , stringRep HotPink1 "hotpink1"+ , stringRep HotPink2 "hotpink2"+ , stringRep HotPink3 "hotpink3"+ , stringRep HotPink4 "hotpink4"+ , stringRep IndianRed "indianred"+ , stringRep IndianRed1 "indianred1"+ , stringRep IndianRed2 "indianred2"+ , stringRep IndianRed3 "indianred3"+ , stringRep IndianRed4 "indianred4"+ , stringRep Indigo "indigo"+ , stringRep Ivory "ivory"+ , stringRep Ivory1 "ivory1"+ , stringRep Ivory2 "ivory2"+ , stringRep Ivory3 "ivory3"+ , stringRep Ivory4 "ivory4"+ , stringRep Khaki "khaki"+ , stringRep Khaki1 "khaki1"+ , stringRep Khaki2 "khaki2"+ , stringRep Khaki3 "khaki3"+ , stringRep Khaki4 "khaki4"+ , stringRep Lavender "lavender"+ , stringRep LavenderBlush "lavenderblush"+ , stringRep LavenderBlush1 "lavenderblush1"+ , stringRep LavenderBlush2 "lavenderblush2"+ , stringRep LavenderBlush3 "lavenderblush3"+ , stringRep LavenderBlush4 "lavenderblush4"+ , stringRep LawnGreen "lawngreen"+ , stringRep LemonChiffon "lemonchiffon"+ , stringRep LemonChiffon1 "lemonchiffon1"+ , stringRep LemonChiffon2 "lemonchiffon2"+ , stringRep LemonChiffon3 "lemonchiffon3"+ , stringRep LemonChiffon4 "lemonchiffon4"+ , stringRep LightBlue "lightblue"+ , stringRep LightBlue1 "lightblue1"+ , stringRep LightBlue2 "lightblue2"+ , stringRep LightBlue3 "lightblue3"+ , stringRep LightBlue4 "lightblue4"+ , stringRep LightCoral "lightcoral"+ , stringRep LightCyan "lightcyan"+ , stringRep LightCyan1 "lightcyan1"+ , stringRep LightCyan2 "lightcyan2"+ , stringRep LightCyan3 "lightcyan3"+ , stringRep LightCyan4 "lightcyan4"+ , stringRep LightGoldenrod "lightgoldenrod"+ , stringRep LightGoldenrod1 "lightgoldenrod1"+ , stringRep LightGoldenrod2 "lightgoldenrod2"+ , stringRep LightGoldenrod3 "lightgoldenrod3"+ , stringRep LightGoldenrod4 "lightgoldenrod4"+ , stringRep LightGoldenrodYellow "lightgoldenrodyellow"+ , stringReps LightGray ["lightgray", "lightgrey"]+ , stringRep LightPink "lightpink"+ , stringRep LightPink1 "lightpink1"+ , stringRep LightPink2 "lightpink2"+ , stringRep LightPink3 "lightpink3"+ , stringRep LightPink4 "lightpink4"+ , stringRep LightSalmon "lightsalmon"+ , stringRep LightSalmon1 "lightsalmon1"+ , stringRep LightSalmon2 "lightsalmon2"+ , stringRep LightSalmon3 "lightsalmon3"+ , stringRep LightSalmon4 "lightsalmon4"+ , stringRep LightSeaGreen "lightseagreen"+ , stringRep LightSkyBlue "lightskyblue"+ , stringRep LightSkyBlue1 "lightskyblue1"+ , stringRep LightSkyBlue2 "lightskyblue2"+ , stringRep LightSkyBlue3 "lightskyblue3"+ , stringRep LightSkyBlue4 "lightskyblue4"+ , stringRep LightSlateBlue "lightslateblue"+ , stringReps LightSlateGray ["lightslategray", "lightslategrey"]+ , stringRep LightSteelBlue "lightsteelblue"+ , stringRep LightSteelBlue1 "lightsteelblue1"+ , stringRep LightSteelBlue2 "lightsteelblue2"+ , stringRep LightSteelBlue3 "lightsteelblue3"+ , stringRep LightSteelBlue4 "lightsteelblue4"+ , stringRep LightYellow "lightyellow"+ , stringRep LightYellow1 "lightyellow1"+ , stringRep LightYellow2 "lightyellow2"+ , stringRep LightYellow3 "lightyellow3"+ , stringRep LightYellow4 "lightyellow4"+ , stringRep LimeGreen "limegreen"+ , stringRep Linen "linen"+ , stringRep Magenta "magenta"+ , stringRep Magenta1 "magenta1"+ , stringRep Magenta2 "magenta2"+ , stringRep Magenta3 "magenta3"+ , stringRep Magenta4 "magenta4"+ , stringRep Maroon "maroon"+ , stringRep Maroon1 "maroon1"+ , stringRep Maroon2 "maroon2"+ , stringRep Maroon3 "maroon3"+ , stringRep Maroon4 "maroon4"+ , stringRep MediumAquamarine "mediumaquamarine"+ , stringRep MediumBlue "mediumblue"+ , stringRep MediumOrchid "mediumorchid"+ , stringRep MediumOrchid1 "mediumorchid1"+ , stringRep MediumOrchid2 "mediumorchid2"+ , stringRep MediumOrchid3 "mediumorchid3"+ , stringRep MediumOrchid4 "mediumorchid4"+ , stringRep MediumPurple "mediumpurple"+ , stringRep MediumPurple1 "mediumpurple1"+ , stringRep MediumPurple2 "mediumpurple2"+ , stringRep MediumPurple3 "mediumpurple3"+ , stringRep MediumPurple4 "mediumpurple4"+ , stringRep MediumSeaGreen "mediumseagreen"+ , stringRep MediumSlateBlue "mediumslateblue"+ , stringRep MediumSpringGreen "mediumspringgreen"+ , stringRep MediumTurquoise "mediumturquoise"+ , stringRep MediumVioletRed "mediumvioletred"+ , stringRep MidnightBlue "midnightblue"+ , stringRep MintCream "mintcream"+ , stringRep MistyRose "mistyrose"+ , stringRep MistyRose1 "mistyrose1"+ , stringRep MistyRose2 "mistyrose2"+ , stringRep MistyRose3 "mistyrose3"+ , stringRep MistyRose4 "mistyrose4"+ , stringRep Moccasin "moccasin"+ , stringRep NavajoWhite "navajowhite"+ , stringRep NavajoWhite1 "navajowhite1"+ , stringRep NavajoWhite2 "navajowhite2"+ , stringRep NavajoWhite3 "navajowhite3"+ , stringRep NavajoWhite4 "navajowhite4"+ , stringRep Navy "navy"+ , stringRep NavyBlue "navyblue"+ , stringRep OldLace "oldlace"+ , stringRep OliveDrab "olivedrab"+ , stringRep OliveDrab1 "olivedrab1"+ , stringRep OliveDrab2 "olivedrab2"+ , stringRep OliveDrab3 "olivedrab3"+ , stringRep OliveDrab4 "olivedrab4"+ , stringRep Orange "orange"+ , stringRep Orange1 "orange1"+ , stringRep Orange2 "orange2"+ , stringRep Orange3 "orange3"+ , stringRep Orange4 "orange4"+ , stringRep OrangeRed "orangered"+ , stringRep OrangeRed1 "orangered1"+ , stringRep OrangeRed2 "orangered2"+ , stringRep OrangeRed3 "orangered3"+ , stringRep OrangeRed4 "orangered4"+ , stringRep Orchid "orchid"+ , stringRep Orchid1 "orchid1"+ , stringRep Orchid2 "orchid2"+ , stringRep Orchid3 "orchid3"+ , stringRep Orchid4 "orchid4"+ , stringRep PaleGoldenrod "palegoldenrod"+ , stringRep PaleGreen "palegreen"+ , stringRep PaleGreen1 "palegreen1"+ , stringRep PaleGreen2 "palegreen2"+ , stringRep PaleGreen3 "palegreen3"+ , stringRep PaleGreen4 "palegreen4"+ , stringRep PaleTurquoise "paleturquoise"+ , stringRep PaleTurquoise1 "paleturquoise1"+ , stringRep PaleTurquoise2 "paleturquoise2"+ , stringRep PaleTurquoise3 "paleturquoise3"+ , stringRep PaleTurquoise4 "paleturquoise4"+ , stringRep PaleVioletRed "palevioletred"+ , stringRep PaleVioletRed1 "palevioletred1"+ , stringRep PaleVioletRed2 "palevioletred2"+ , stringRep PaleVioletRed3 "palevioletred3"+ , stringRep PaleVioletRed4 "palevioletred4"+ , stringRep PapayaWhip "papayawhip"+ , stringRep PeachPuff "peachpuff"+ , stringRep PeachPuff1 "peachpuff1"+ , stringRep PeachPuff2 "peachpuff2"+ , stringRep PeachPuff3 "peachpuff3"+ , stringRep PeachPuff4 "peachpuff4"+ , stringRep Peru "peru"+ , stringRep Pink "pink"+ , stringRep Pink1 "pink1"+ , stringRep Pink2 "pink2"+ , stringRep Pink3 "pink3"+ , stringRep Pink4 "pink4"+ , stringRep Plum "plum"+ , stringRep Plum1 "plum1"+ , stringRep Plum2 "plum2"+ , stringRep Plum3 "plum3"+ , stringRep Plum4 "plum4"+ , stringRep PowderBlue "powderblue"+ , stringRep Purple "purple"+ , stringRep Purple1 "purple1"+ , stringRep Purple2 "purple2"+ , stringRep Purple3 "purple3"+ , stringRep Purple4 "purple4"+ , stringRep Red "red"+ , stringRep Red1 "red1"+ , stringRep Red2 "red2"+ , stringRep Red3 "red3"+ , stringRep Red4 "red4"+ , stringRep RosyBrown "rosybrown"+ , stringRep RosyBrown1 "rosybrown1"+ , stringRep RosyBrown2 "rosybrown2"+ , stringRep RosyBrown3 "rosybrown3"+ , stringRep RosyBrown4 "rosybrown4"+ , stringRep RoyalBlue "royalblue"+ , stringRep RoyalBlue1 "royalblue1"+ , stringRep RoyalBlue2 "royalblue2"+ , stringRep RoyalBlue3 "royalblue3"+ , stringRep RoyalBlue4 "royalblue4"+ , stringRep SaddleBrown "saddlebrown"+ , stringRep Salmon "salmon"+ , stringRep Salmon1 "salmon1"+ , stringRep Salmon2 "salmon2"+ , stringRep Salmon3 "salmon3"+ , stringRep Salmon4 "salmon4"+ , stringRep SandyBrown "sandybrown"+ , stringRep SeaGreen "seagreen"+ , stringRep SeaGreen1 "seagreen1"+ , stringRep SeaGreen2 "seagreen2"+ , stringRep SeaGreen3 "seagreen3"+ , stringRep SeaGreen4 "seagreen4"+ , stringRep SeaShell "seashell"+ , stringRep SeaShell1 "seashell1"+ , stringRep SeaShell2 "seashell2"+ , stringRep SeaShell3 "seashell3"+ , stringRep SeaShell4 "seashell4"+ , stringRep Sienna "sienna"+ , stringRep Sienna1 "sienna1"+ , stringRep Sienna2 "sienna2"+ , stringRep Sienna3 "sienna3"+ , stringRep Sienna4 "sienna4"+ , stringRep SkyBlue "skyblue"+ , stringRep SkyBlue1 "skyblue1"+ , stringRep SkyBlue2 "skyblue2"+ , stringRep SkyBlue3 "skyblue3"+ , stringRep SkyBlue4 "skyblue4"+ , stringRep SlateBlue "slateblue"+ , stringRep SlateBlue1 "slateblue1"+ , stringRep SlateBlue2 "slateblue2"+ , stringRep SlateBlue3 "slateblue3"+ , stringRep SlateBlue4 "slateblue4"+ , stringReps SlateGray ["slategray", "slategrey"]+ , stringReps SlateGray1 ["slategray1", "slategrey1"]+ , stringReps SlateGray2 ["slategray2", "slategrey2"]+ , stringReps SlateGray3 ["slategray3", "slategrey3"]+ , stringReps SlateGray4 ["slategray4", "slategrey4"]+ , stringRep Snow "snow"+ , stringRep Snow1 "snow1"+ , stringRep Snow2 "snow2"+ , stringRep Snow3 "snow3"+ , stringRep Snow4 "snow4"+ , stringRep SpringGreen "springgreen"+ , stringRep SpringGreen1 "springgreen1"+ , stringRep SpringGreen2 "springgreen2"+ , stringRep SpringGreen3 "springgreen3"+ , stringRep SpringGreen4 "springgreen4"+ , stringRep SteelBlue "steelblue"+ , stringRep SteelBlue1 "steelblue1"+ , stringRep SteelBlue2 "steelblue2"+ , stringRep SteelBlue3 "steelblue3"+ , stringRep SteelBlue4 "steelblue4"+ , stringRep Tan "tan"+ , stringRep Tan1 "tan1"+ , stringRep Tan2 "tan2"+ , stringRep Tan3 "tan3"+ , stringRep Tan4 "tan4"+ , stringRep Thistle "thistle"+ , stringRep Thistle1 "thistle1"+ , stringRep Thistle2 "thistle2"+ , stringRep Thistle3 "thistle3"+ , stringRep Thistle4 "thistle4"+ , stringRep Tomato "tomato"+ , stringRep Tomato1 "tomato1"+ , stringRep Tomato2 "tomato2"+ , stringRep Tomato3 "tomato3"+ , stringRep Tomato4 "tomato4"+ , stringReps Transparent ["transparent", "invis", "none"]+ , stringRep Turquoise "turquoise"+ , stringRep Turquoise1 "turquoise1"+ , stringRep Turquoise2 "turquoise2"+ , stringRep Turquoise3 "turquoise3"+ , stringRep Turquoise4 "turquoise4"+ , stringRep Violet "violet"+ , stringRep VioletRed "violetred"+ , stringRep VioletRed1 "violetred1"+ , stringRep VioletRed2 "violetred2"+ , stringRep VioletRed3 "violetred3"+ , stringRep VioletRed4 "violetred4"+ , stringRep Wheat "wheat"+ , stringRep Wheat1 "wheat1"+ , stringRep Wheat2 "wheat2"+ , stringRep Wheat3 "wheat3"+ , stringRep Wheat4 "wheat4"+ , stringRep White "white"+ , stringRep WhiteSmoke "whitesmoke"+ , stringRep Yellow "yellow"+ , stringRep Yellow1 "yellow1"+ , stringRep Yellow2 "yellow2"+ , stringRep Yellow3 "yellow3"+ , stringRep Yellow4 "yellow4"+ , stringRep YellowGreen "yellowgreen"+ ]++-- | Attempt to convert a 'Color' into a 'Colour' value with an alpha+-- channel. The use of 'Maybe' is because 'BrewerColor' values+-- cannot be converted without knowing which actual 'BrewerName' and+-- level color scheme is being used.+toColour :: Color -> Maybe (AlphaColour Double)+toColour (RGB r g b) = Just . opaque $ sRGB24 r g b+toColour (RGBA r g b a) = Just . withOpacity (sRGB24 r g b) $ toOpacity a+-- Colour expects the hue to be an angle, so multiply by 360+toColour (HSV h s v) = Just . opaque . uncurryRGB sRGB $ hsv (h*360) s v+toColour (X11Color c) = Just $ x11Colour c+toColour BrewerColor{} = Nothing++toOpacity :: Word8 -> Double+toOpacity a = fromIntegral a / maxWord++-- | Convert an 'X11Color' to its equivalent 'Colour' value. Note+-- that it uses 'AlphaColour' because of 'Transparent'; all other+-- 'X11Color' values are completely opaque.+x11Colour :: X11Color -> AlphaColour Double+x11Colour AliceBlue = opaque $ sRGB24 240 248 255+x11Colour AntiqueWhite = opaque $ sRGB24 250 235 215+x11Colour AntiqueWhite1 = opaque $ sRGB24 255 239 219+x11Colour AntiqueWhite2 = opaque $ sRGB24 238 223 204+x11Colour AntiqueWhite3 = opaque $ sRGB24 205 192 176+x11Colour AntiqueWhite4 = opaque $ sRGB24 139 131 120+x11Colour Aquamarine = opaque $ sRGB24 127 255 212+x11Colour Aquamarine1 = opaque $ sRGB24 127 255 212+x11Colour Aquamarine2 = opaque $ sRGB24 118 238 198+x11Colour Aquamarine3 = opaque $ sRGB24 102 205 170+x11Colour Aquamarine4 = opaque $ sRGB24 69 139 116+x11Colour Azure = opaque $ sRGB24 240 255 255+x11Colour Azure1 = opaque $ sRGB24 240 255 255+x11Colour Azure2 = opaque $ sRGB24 224 238 238+x11Colour Azure3 = opaque $ sRGB24 193 205 205+x11Colour Azure4 = opaque $ sRGB24 131 139 139+x11Colour Beige = opaque $ sRGB24 245 245 220+x11Colour Bisque = opaque $ sRGB24 255 228 196+x11Colour Bisque1 = opaque $ sRGB24 255 228 196+x11Colour Bisque2 = opaque $ sRGB24 238 213 183+x11Colour Bisque3 = opaque $ sRGB24 205 183 158+x11Colour Bisque4 = opaque $ sRGB24 139 125 107+x11Colour Black = opaque $ sRGB24 0 0 0+x11Colour BlanchedAlmond = opaque $ sRGB24 255 235 205+x11Colour Blue = opaque $ sRGB24 0 0 255+x11Colour Blue1 = opaque $ sRGB24 0 0 255+x11Colour Blue2 = opaque $ sRGB24 0 0 238+x11Colour Blue3 = opaque $ sRGB24 0 0 205+x11Colour Blue4 = opaque $ sRGB24 0 0 139+x11Colour BlueViolet = opaque $ sRGB24 138 43 226+x11Colour Brown = opaque $ sRGB24 165 42 42+x11Colour Brown1 = opaque $ sRGB24 255 64 64+x11Colour Brown2 = opaque $ sRGB24 238 59 59+x11Colour Brown3 = opaque $ sRGB24 205 51 51+x11Colour Brown4 = opaque $ sRGB24 139 35 35+x11Colour Burlywood = opaque $ sRGB24 222 184 135+x11Colour Burlywood1 = opaque $ sRGB24 255 211 155+x11Colour Burlywood2 = opaque $ sRGB24 238 197 145+x11Colour Burlywood3 = opaque $ sRGB24 205 170 125+x11Colour Burlywood4 = opaque $ sRGB24 139 115 85+x11Colour CadetBlue = opaque $ sRGB24 95 158 160+x11Colour CadetBlue1 = opaque $ sRGB24 152 245 255+x11Colour CadetBlue2 = opaque $ sRGB24 142 229 238+x11Colour CadetBlue3 = opaque $ sRGB24 122 197 205+x11Colour CadetBlue4 = opaque $ sRGB24 83 134 139+x11Colour Chartreuse = opaque $ sRGB24 127 255 0+x11Colour Chartreuse1 = opaque $ sRGB24 127 255 0+x11Colour Chartreuse2 = opaque $ sRGB24 118 238 0+x11Colour Chartreuse3 = opaque $ sRGB24 102 205 0+x11Colour Chartreuse4 = opaque $ sRGB24 69 139 0+x11Colour Chocolate = opaque $ sRGB24 210 105 30+x11Colour Chocolate1 = opaque $ sRGB24 255 127 36+x11Colour Chocolate2 = opaque $ sRGB24 238 118 33+x11Colour Chocolate3 = opaque $ sRGB24 205 102 29+x11Colour Chocolate4 = opaque $ sRGB24 139 69 19+x11Colour Coral = opaque $ sRGB24 255 127 80+x11Colour Coral1 = opaque $ sRGB24 255 114 86+x11Colour Coral2 = opaque $ sRGB24 238 106 80+x11Colour Coral3 = opaque $ sRGB24 205 91 69+x11Colour Coral4 = opaque $ sRGB24 139 62 47+x11Colour CornFlowerBlue = opaque $ sRGB24 100 149 237+x11Colour CornSilk = opaque $ sRGB24 255 248 220+x11Colour CornSilk1 = opaque $ sRGB24 255 248 220+x11Colour CornSilk2 = opaque $ sRGB24 238 232 205+x11Colour CornSilk3 = opaque $ sRGB24 205 200 177+x11Colour CornSilk4 = opaque $ sRGB24 139 136 120+x11Colour Crimson = opaque $ sRGB24 220 20 60+x11Colour Cyan = opaque $ sRGB24 0 255 255+x11Colour Cyan1 = opaque $ sRGB24 0 255 255+x11Colour Cyan2 = opaque $ sRGB24 0 238 238+x11Colour Cyan3 = opaque $ sRGB24 0 205 205+x11Colour Cyan4 = opaque $ sRGB24 0 139 139+x11Colour DarkGoldenrod = opaque $ sRGB24 184 134 11+x11Colour DarkGoldenrod1 = opaque $ sRGB24 255 185 15+x11Colour DarkGoldenrod2 = opaque $ sRGB24 238 173 14+x11Colour DarkGoldenrod3 = opaque $ sRGB24 205 149 12+x11Colour DarkGoldenrod4 = opaque $ sRGB24 139 101 8+x11Colour DarkGreen = opaque $ sRGB24 0 100 0+x11Colour Darkkhaki = opaque $ sRGB24 189 183 107+x11Colour DarkOliveGreen = opaque $ sRGB24 85 107 47+x11Colour DarkOliveGreen1 = opaque $ sRGB24 202 255 112+x11Colour DarkOliveGreen2 = opaque $ sRGB24 188 238 104+x11Colour DarkOliveGreen3 = opaque $ sRGB24 162 205 90+x11Colour DarkOliveGreen4 = opaque $ sRGB24 110 139 61+x11Colour DarkOrange = opaque $ sRGB24 255 140 0+x11Colour DarkOrange1 = opaque $ sRGB24 255 127 0+x11Colour DarkOrange2 = opaque $ sRGB24 238 118 0+x11Colour DarkOrange3 = opaque $ sRGB24 205 102 0+x11Colour DarkOrange4 = opaque $ sRGB24 139 69 0+x11Colour DarkOrchid = opaque $ sRGB24 153 50 204+x11Colour DarkOrchid1 = opaque $ sRGB24 191 62 255+x11Colour DarkOrchid2 = opaque $ sRGB24 178 58 238+x11Colour DarkOrchid3 = opaque $ sRGB24 154 50 205+x11Colour DarkOrchid4 = opaque $ sRGB24 104 34 139+x11Colour DarkSalmon = opaque $ sRGB24 233 150 122+x11Colour DarkSeaGreen = opaque $ sRGB24 143 188 143+x11Colour DarkSeaGreen1 = opaque $ sRGB24 193 255 193+x11Colour DarkSeaGreen2 = opaque $ sRGB24 180 238 180+x11Colour DarkSeaGreen3 = opaque $ sRGB24 155 205 155+x11Colour DarkSeaGreen4 = opaque $ sRGB24 105 139 105+x11Colour DarkSlateBlue = opaque $ sRGB24 72 61 139+x11Colour DarkSlateGray = opaque $ sRGB24 47 79 79+x11Colour DarkSlateGray1 = opaque $ sRGB24 151 255 255+x11Colour DarkSlateGray2 = opaque $ sRGB24 141 238 238+x11Colour DarkSlateGray3 = opaque $ sRGB24 121 205 205+x11Colour DarkSlateGray4 = opaque $ sRGB24 82 139 139+x11Colour DarkTurquoise = opaque $ sRGB24 0 206 209+x11Colour DarkViolet = opaque $ sRGB24 148 0 211+x11Colour DeepPink = opaque $ sRGB24 255 20 147+x11Colour DeepPink1 = opaque $ sRGB24 255 20 147+x11Colour DeepPink2 = opaque $ sRGB24 238 18 137+x11Colour DeepPink3 = opaque $ sRGB24 205 16 118+x11Colour DeepPink4 = opaque $ sRGB24 139 10 80+x11Colour DeepSkyBlue = opaque $ sRGB24 0 191 255+x11Colour DeepSkyBlue1 = opaque $ sRGB24 0 191 255+x11Colour DeepSkyBlue2 = opaque $ sRGB24 0 178 238+x11Colour DeepSkyBlue3 = opaque $ sRGB24 0 154 205+x11Colour DeepSkyBlue4 = opaque $ sRGB24 0 104 139+x11Colour DimGray = opaque $ sRGB24 105 105 105+x11Colour DodgerBlue = opaque $ sRGB24 30 144 255+x11Colour DodgerBlue1 = opaque $ sRGB24 30 144 255+x11Colour DodgerBlue2 = opaque $ sRGB24 28 134 238+x11Colour DodgerBlue3 = opaque $ sRGB24 24 116 205+x11Colour DodgerBlue4 = opaque $ sRGB24 16 78 139+x11Colour Firebrick = opaque $ sRGB24 178 34 34+x11Colour Firebrick1 = opaque $ sRGB24 255 48 48+x11Colour Firebrick2 = opaque $ sRGB24 238 44 44+x11Colour Firebrick3 = opaque $ sRGB24 205 38 38+x11Colour Firebrick4 = opaque $ sRGB24 139 26 26+x11Colour FloralWhite = opaque $ sRGB24 255 250 240+x11Colour ForestGreen = opaque $ sRGB24 34 139 34+x11Colour Gainsboro = opaque $ sRGB24 220 220 220+x11Colour GhostWhite = opaque $ sRGB24 248 248 255+x11Colour Gold = opaque $ sRGB24 255 215 0+x11Colour Gold1 = opaque $ sRGB24 255 215 0+x11Colour Gold2 = opaque $ sRGB24 238 201 0+x11Colour Gold3 = opaque $ sRGB24 205 173 0+x11Colour Gold4 = opaque $ sRGB24 139 117 0+x11Colour Goldenrod = opaque $ sRGB24 218 165 32+x11Colour Goldenrod1 = opaque $ sRGB24 255 193 37+x11Colour Goldenrod2 = opaque $ sRGB24 238 180 34+x11Colour Goldenrod3 = opaque $ sRGB24 205 155 29+x11Colour Goldenrod4 = opaque $ sRGB24 139 105 20+x11Colour Gray = opaque $ sRGB24 192 192 192+x11Colour Gray0 = opaque $ sRGB24 0 0 0+x11Colour Gray1 = opaque $ sRGB24 3 3 3+x11Colour Gray2 = opaque $ sRGB24 5 5 5+x11Colour Gray3 = opaque $ sRGB24 8 8 8+x11Colour Gray4 = opaque $ sRGB24 10 10 10+x11Colour Gray5 = opaque $ sRGB24 13 13 13+x11Colour Gray6 = opaque $ sRGB24 15 15 15+x11Colour Gray7 = opaque $ sRGB24 18 18 18+x11Colour Gray8 = opaque $ sRGB24 20 20 20+x11Colour Gray9 = opaque $ sRGB24 23 23 23+x11Colour Gray10 = opaque $ sRGB24 26 26 26+x11Colour Gray11 = opaque $ sRGB24 28 28 28+x11Colour Gray12 = opaque $ sRGB24 31 31 31+x11Colour Gray13 = opaque $ sRGB24 33 33 33+x11Colour Gray14 = opaque $ sRGB24 36 36 36+x11Colour Gray15 = opaque $ sRGB24 38 38 38+x11Colour Gray16 = opaque $ sRGB24 41 41 41+x11Colour Gray17 = opaque $ sRGB24 43 43 43+x11Colour Gray18 = opaque $ sRGB24 46 46 46+x11Colour Gray19 = opaque $ sRGB24 48 48 48+x11Colour Gray20 = opaque $ sRGB24 51 51 51+x11Colour Gray21 = opaque $ sRGB24 54 54 54+x11Colour Gray22 = opaque $ sRGB24 56 56 56+x11Colour Gray23 = opaque $ sRGB24 59 59 59+x11Colour Gray24 = opaque $ sRGB24 61 61 61+x11Colour Gray25 = opaque $ sRGB24 64 64 64+x11Colour Gray26 = opaque $ sRGB24 66 66 66+x11Colour Gray27 = opaque $ sRGB24 69 69 69+x11Colour Gray28 = opaque $ sRGB24 71 71 71+x11Colour Gray29 = opaque $ sRGB24 74 74 74+x11Colour Gray30 = opaque $ sRGB24 77 77 77+x11Colour Gray31 = opaque $ sRGB24 79 79 79+x11Colour Gray32 = opaque $ sRGB24 82 82 82+x11Colour Gray33 = opaque $ sRGB24 84 84 84+x11Colour Gray34 = opaque $ sRGB24 87 87 87+x11Colour Gray35 = opaque $ sRGB24 89 89 89+x11Colour Gray36 = opaque $ sRGB24 92 92 92+x11Colour Gray37 = opaque $ sRGB24 94 94 94+x11Colour Gray38 = opaque $ sRGB24 97 97 97+x11Colour Gray39 = opaque $ sRGB24 99 99 99+x11Colour Gray40 = opaque $ sRGB24 102 102 102+x11Colour Gray41 = opaque $ sRGB24 105 105 105+x11Colour Gray42 = opaque $ sRGB24 107 107 107+x11Colour Gray43 = opaque $ sRGB24 110 110 110+x11Colour Gray44 = opaque $ sRGB24 112 112 112+x11Colour Gray45 = opaque $ sRGB24 115 115 115+x11Colour Gray46 = opaque $ sRGB24 117 117 117+x11Colour Gray47 = opaque $ sRGB24 120 120 120+x11Colour Gray48 = opaque $ sRGB24 122 122 122+x11Colour Gray49 = opaque $ sRGB24 125 125 125+x11Colour Gray50 = opaque $ sRGB24 127 127 127+x11Colour Gray51 = opaque $ sRGB24 130 130 130+x11Colour Gray52 = opaque $ sRGB24 133 133 133+x11Colour Gray53 = opaque $ sRGB24 135 135 135+x11Colour Gray54 = opaque $ sRGB24 138 138 138+x11Colour Gray55 = opaque $ sRGB24 140 140 140+x11Colour Gray56 = opaque $ sRGB24 143 143 143+x11Colour Gray57 = opaque $ sRGB24 145 145 145+x11Colour Gray58 = opaque $ sRGB24 148 148 148+x11Colour Gray59 = opaque $ sRGB24 150 150 150+x11Colour Gray60 = opaque $ sRGB24 153 153 153+x11Colour Gray61 = opaque $ sRGB24 156 156 156+x11Colour Gray62 = opaque $ sRGB24 158 158 158+x11Colour Gray63 = opaque $ sRGB24 161 161 161+x11Colour Gray64 = opaque $ sRGB24 163 163 163+x11Colour Gray65 = opaque $ sRGB24 166 166 166+x11Colour Gray66 = opaque $ sRGB24 168 168 168+x11Colour Gray67 = opaque $ sRGB24 171 171 171+x11Colour Gray68 = opaque $ sRGB24 173 173 173+x11Colour Gray69 = opaque $ sRGB24 176 176 176+x11Colour Gray70 = opaque $ sRGB24 179 179 179+x11Colour Gray71 = opaque $ sRGB24 181 181 181+x11Colour Gray72 = opaque $ sRGB24 184 184 184+x11Colour Gray73 = opaque $ sRGB24 186 186 186+x11Colour Gray74 = opaque $ sRGB24 189 189 189+x11Colour Gray75 = opaque $ sRGB24 191 191 191+x11Colour Gray76 = opaque $ sRGB24 194 194 194+x11Colour Gray77 = opaque $ sRGB24 196 196 196+x11Colour Gray78 = opaque $ sRGB24 199 199 199+x11Colour Gray79 = opaque $ sRGB24 201 201 201+x11Colour Gray80 = opaque $ sRGB24 204 204 204+x11Colour Gray81 = opaque $ sRGB24 207 207 207+x11Colour Gray82 = opaque $ sRGB24 209 209 209+x11Colour Gray83 = opaque $ sRGB24 212 212 212+x11Colour Gray84 = opaque $ sRGB24 214 214 214+x11Colour Gray85 = opaque $ sRGB24 217 217 217+x11Colour Gray86 = opaque $ sRGB24 219 219 219+x11Colour Gray87 = opaque $ sRGB24 222 222 222+x11Colour Gray88 = opaque $ sRGB24 224 224 224+x11Colour Gray89 = opaque $ sRGB24 227 227 227+x11Colour Gray90 = opaque $ sRGB24 229 229 229+x11Colour Gray91 = opaque $ sRGB24 232 232 232+x11Colour Gray92 = opaque $ sRGB24 235 235 235+x11Colour Gray93 = opaque $ sRGB24 237 237 237+x11Colour Gray94 = opaque $ sRGB24 240 240 240+x11Colour Gray95 = opaque $ sRGB24 242 242 242+x11Colour Gray96 = opaque $ sRGB24 245 245 245+x11Colour Gray97 = opaque $ sRGB24 247 247 247+x11Colour Gray98 = opaque $ sRGB24 250 250 250+x11Colour Gray99 = opaque $ sRGB24 252 252 252+x11Colour Gray100 = opaque $ sRGB24 255 255 255+x11Colour Green = opaque $ sRGB24 0 255 0+x11Colour Green1 = opaque $ sRGB24 0 255 0+x11Colour Green2 = opaque $ sRGB24 0 238 0+x11Colour Green3 = opaque $ sRGB24 0 205 0+x11Colour Green4 = opaque $ sRGB24 0 139 0+x11Colour GreenYellow = opaque $ sRGB24 173 255 47+x11Colour HoneyDew = opaque $ sRGB24 240 255 240+x11Colour HoneyDew1 = opaque $ sRGB24 240 255 240+x11Colour HoneyDew2 = opaque $ sRGB24 224 238 224+x11Colour HoneyDew3 = opaque $ sRGB24 193 205 193+x11Colour HoneyDew4 = opaque $ sRGB24 131 139 131+x11Colour HotPink = opaque $ sRGB24 255 105 180+x11Colour HotPink1 = opaque $ sRGB24 255 110 180+x11Colour HotPink2 = opaque $ sRGB24 238 106 167+x11Colour HotPink3 = opaque $ sRGB24 205 96 144+x11Colour HotPink4 = opaque $ sRGB24 139 58 98+x11Colour IndianRed = opaque $ sRGB24 205 92 92+x11Colour IndianRed1 = opaque $ sRGB24 255 106 106+x11Colour IndianRed2 = opaque $ sRGB24 238 99 99+x11Colour IndianRed3 = opaque $ sRGB24 205 85 85+x11Colour IndianRed4 = opaque $ sRGB24 139 58 58+x11Colour Indigo = opaque $ sRGB24 75 0 130+x11Colour Ivory = opaque $ sRGB24 255 255 240+x11Colour Ivory1 = opaque $ sRGB24 255 255 240+x11Colour Ivory2 = opaque $ sRGB24 238 238 224+x11Colour Ivory3 = opaque $ sRGB24 205 205 193+x11Colour Ivory4 = opaque $ sRGB24 139 139 131+x11Colour Khaki = opaque $ sRGB24 240 230 140+x11Colour Khaki1 = opaque $ sRGB24 255 246 143+x11Colour Khaki2 = opaque $ sRGB24 238 230 133+x11Colour Khaki3 = opaque $ sRGB24 205 198 115+x11Colour Khaki4 = opaque $ sRGB24 139 134 78+x11Colour Lavender = opaque $ sRGB24 230 230 250+x11Colour LavenderBlush = opaque $ sRGB24 255 240 245+x11Colour LavenderBlush1 = opaque $ sRGB24 255 240 245+x11Colour LavenderBlush2 = opaque $ sRGB24 238 224 229+x11Colour LavenderBlush3 = opaque $ sRGB24 205 193 197+x11Colour LavenderBlush4 = opaque $ sRGB24 139 131 134+x11Colour LawnGreen = opaque $ sRGB24 124 252 0+x11Colour LemonChiffon = opaque $ sRGB24 255 250 205+x11Colour LemonChiffon1 = opaque $ sRGB24 255 250 205+x11Colour LemonChiffon2 = opaque $ sRGB24 238 233 191+x11Colour LemonChiffon3 = opaque $ sRGB24 205 201 165+x11Colour LemonChiffon4 = opaque $ sRGB24 139 137 112+x11Colour LightBlue = opaque $ sRGB24 173 216 230+x11Colour LightBlue1 = opaque $ sRGB24 191 239 255+x11Colour LightBlue2 = opaque $ sRGB24 178 223 238+x11Colour LightBlue3 = opaque $ sRGB24 154 192 205+x11Colour LightBlue4 = opaque $ sRGB24 104 131 139+x11Colour LightCoral = opaque $ sRGB24 240 128 128+x11Colour LightCyan = opaque $ sRGB24 224 255 255+x11Colour LightCyan1 = opaque $ sRGB24 224 255 255+x11Colour LightCyan2 = opaque $ sRGB24 209 238 238+x11Colour LightCyan3 = opaque $ sRGB24 180 205 205+x11Colour LightCyan4 = opaque $ sRGB24 122 139 139+x11Colour LightGoldenrod = opaque $ sRGB24 238 221 130+x11Colour LightGoldenrod1 = opaque $ sRGB24 255 236 139+x11Colour LightGoldenrod2 = opaque $ sRGB24 238 220 130+x11Colour LightGoldenrod3 = opaque $ sRGB24 205 190 112+x11Colour LightGoldenrod4 = opaque $ sRGB24 139 129 76+x11Colour LightGoldenrodYellow = opaque $ sRGB24 250 250 210+x11Colour LightGray = opaque $ sRGB24 211 211 211+x11Colour LightPink = opaque $ sRGB24 255 182 193+x11Colour LightPink1 = opaque $ sRGB24 255 174 185+x11Colour LightPink2 = opaque $ sRGB24 238 162 173+x11Colour LightPink3 = opaque $ sRGB24 205 140 149+x11Colour LightPink4 = opaque $ sRGB24 139 95 101+x11Colour LightSalmon = opaque $ sRGB24 255 160 122+x11Colour LightSalmon1 = opaque $ sRGB24 255 160 122+x11Colour LightSalmon2 = opaque $ sRGB24 238 149 114+x11Colour LightSalmon3 = opaque $ sRGB24 205 129 98+x11Colour LightSalmon4 = opaque $ sRGB24 139 87 66+x11Colour LightSeaGreen = opaque $ sRGB24 32 178 170+x11Colour LightSkyBlue = opaque $ sRGB24 135 206 250+x11Colour LightSkyBlue1 = opaque $ sRGB24 176 226 255+x11Colour LightSkyBlue2 = opaque $ sRGB24 164 211 238+x11Colour LightSkyBlue3 = opaque $ sRGB24 141 182 205+x11Colour LightSkyBlue4 = opaque $ sRGB24 96 123 139+x11Colour LightSlateBlue = opaque $ sRGB24 132 112 255+x11Colour LightSlateGray = opaque $ sRGB24 119 136 153+x11Colour LightSteelBlue = opaque $ sRGB24 176 196 222+x11Colour LightSteelBlue1 = opaque $ sRGB24 202 225 255+x11Colour LightSteelBlue2 = opaque $ sRGB24 188 210 238+x11Colour LightSteelBlue3 = opaque $ sRGB24 162 181 205+x11Colour LightSteelBlue4 = opaque $ sRGB24 110 123 139+x11Colour LightYellow = opaque $ sRGB24 255 255 224+x11Colour LightYellow1 = opaque $ sRGB24 255 255 224+x11Colour LightYellow2 = opaque $ sRGB24 238 238 209+x11Colour LightYellow3 = opaque $ sRGB24 205 205 180+x11Colour LightYellow4 = opaque $ sRGB24 139 139 122+x11Colour LimeGreen = opaque $ sRGB24 50 205 50+x11Colour Linen = opaque $ sRGB24 250 240 230+x11Colour Magenta = opaque $ sRGB24 255 0 255+x11Colour Magenta1 = opaque $ sRGB24 255 0 255+x11Colour Magenta2 = opaque $ sRGB24 238 0 238+x11Colour Magenta3 = opaque $ sRGB24 205 0 205+x11Colour Magenta4 = opaque $ sRGB24 139 0 139+x11Colour Maroon = opaque $ sRGB24 176 48 96+x11Colour Maroon1 = opaque $ sRGB24 255 52 179+x11Colour Maroon2 = opaque $ sRGB24 238 48 167+x11Colour Maroon3 = opaque $ sRGB24 205 41 144+x11Colour Maroon4 = opaque $ sRGB24 139 28 98+x11Colour MediumAquamarine = opaque $ sRGB24 102 205 170+x11Colour MediumBlue = opaque $ sRGB24 0 0 205+x11Colour MediumOrchid = opaque $ sRGB24 186 85 211+x11Colour MediumOrchid1 = opaque $ sRGB24 224 102 255+x11Colour MediumOrchid2 = opaque $ sRGB24 209 95 238+x11Colour MediumOrchid3 = opaque $ sRGB24 180 82 205+x11Colour MediumOrchid4 = opaque $ sRGB24 122 55 139+x11Colour MediumPurple = opaque $ sRGB24 147 112 219+x11Colour MediumPurple1 = opaque $ sRGB24 171 130 255+x11Colour MediumPurple2 = opaque $ sRGB24 159 121 238+x11Colour MediumPurple3 = opaque $ sRGB24 137 104 205+x11Colour MediumPurple4 = opaque $ sRGB24 93 71 139+x11Colour MediumSeaGreen = opaque $ sRGB24 60 179 113+x11Colour MediumSlateBlue = opaque $ sRGB24 123 104 238+x11Colour MediumSpringGreen = opaque $ sRGB24 0 250 154+x11Colour MediumTurquoise = opaque $ sRGB24 72 209 204+x11Colour MediumVioletRed = opaque $ sRGB24 199 21 133+x11Colour MidnightBlue = opaque $ sRGB24 25 25 112+x11Colour MintCream = opaque $ sRGB24 245 255 250+x11Colour MistyRose = opaque $ sRGB24 255 228 225+x11Colour MistyRose1 = opaque $ sRGB24 255 228 225+x11Colour MistyRose2 = opaque $ sRGB24 238 213 210+x11Colour MistyRose3 = opaque $ sRGB24 205 183 181+x11Colour MistyRose4 = opaque $ sRGB24 139 125 123+x11Colour Moccasin = opaque $ sRGB24 255 228 181+x11Colour NavajoWhite = opaque $ sRGB24 255 222 173+x11Colour NavajoWhite1 = opaque $ sRGB24 255 222 173+x11Colour NavajoWhite2 = opaque $ sRGB24 238 207 161+x11Colour NavajoWhite3 = opaque $ sRGB24 205 179 139+x11Colour NavajoWhite4 = opaque $ sRGB24 139 121 94+x11Colour Navy = opaque $ sRGB24 0 0 128+x11Colour NavyBlue = opaque $ sRGB24 0 0 128+x11Colour OldLace = opaque $ sRGB24 253 245 230+x11Colour OliveDrab = opaque $ sRGB24 107 142 35+x11Colour OliveDrab1 = opaque $ sRGB24 192 255 62+x11Colour OliveDrab2 = opaque $ sRGB24 179 238 58+x11Colour OliveDrab3 = opaque $ sRGB24 154 205 50+x11Colour OliveDrab4 = opaque $ sRGB24 105 139 34+x11Colour Orange = opaque $ sRGB24 255 165 0+x11Colour Orange1 = opaque $ sRGB24 255 165 0+x11Colour Orange2 = opaque $ sRGB24 238 154 0+x11Colour Orange3 = opaque $ sRGB24 205 133 0+x11Colour Orange4 = opaque $ sRGB24 139 90 0+x11Colour OrangeRed = opaque $ sRGB24 255 69 0+x11Colour OrangeRed1 = opaque $ sRGB24 255 69 0+x11Colour OrangeRed2 = opaque $ sRGB24 238 64 0+x11Colour OrangeRed3 = opaque $ sRGB24 205 55 0+x11Colour OrangeRed4 = opaque $ sRGB24 139 37 0+x11Colour Orchid = opaque $ sRGB24 218 112 214+x11Colour Orchid1 = opaque $ sRGB24 255 131 250+x11Colour Orchid2 = opaque $ sRGB24 238 122 233+x11Colour Orchid3 = opaque $ sRGB24 205 105 201+x11Colour Orchid4 = opaque $ sRGB24 139 71 137+x11Colour PaleGoldenrod = opaque $ sRGB24 238 232 170+x11Colour PaleGreen = opaque $ sRGB24 152 251 152+x11Colour PaleGreen1 = opaque $ sRGB24 154 255 154+x11Colour PaleGreen2 = opaque $ sRGB24 144 238 144+x11Colour PaleGreen3 = opaque $ sRGB24 124 205 124+x11Colour PaleGreen4 = opaque $ sRGB24 84 139 84+x11Colour PaleTurquoise = opaque $ sRGB24 175 238 238+x11Colour PaleTurquoise1 = opaque $ sRGB24 187 255 255+x11Colour PaleTurquoise2 = opaque $ sRGB24 174 238 238+x11Colour PaleTurquoise3 = opaque $ sRGB24 150 205 205+x11Colour PaleTurquoise4 = opaque $ sRGB24 102 139 139+x11Colour PaleVioletRed = opaque $ sRGB24 219 112 147+x11Colour PaleVioletRed1 = opaque $ sRGB24 255 130 171+x11Colour PaleVioletRed2 = opaque $ sRGB24 238 121 159+x11Colour PaleVioletRed3 = opaque $ sRGB24 205 104 137+x11Colour PaleVioletRed4 = opaque $ sRGB24 139 71 93+x11Colour PapayaWhip = opaque $ sRGB24 255 239 213+x11Colour PeachPuff = opaque $ sRGB24 255 218 185+x11Colour PeachPuff1 = opaque $ sRGB24 255 218 185+x11Colour PeachPuff2 = opaque $ sRGB24 238 203 173+x11Colour PeachPuff3 = opaque $ sRGB24 205 175 149+x11Colour PeachPuff4 = opaque $ sRGB24 139 119 101+x11Colour Peru = opaque $ sRGB24 205 133 63+x11Colour Pink = opaque $ sRGB24 255 192 203+x11Colour Pink1 = opaque $ sRGB24 255 181 197+x11Colour Pink2 = opaque $ sRGB24 238 169 184+x11Colour Pink3 = opaque $ sRGB24 205 145 158+x11Colour Pink4 = opaque $ sRGB24 139 99 108+x11Colour Plum = opaque $ sRGB24 221 160 221+x11Colour Plum1 = opaque $ sRGB24 255 187 255+x11Colour Plum2 = opaque $ sRGB24 238 174 238+x11Colour Plum3 = opaque $ sRGB24 205 150 205+x11Colour Plum4 = opaque $ sRGB24 139 102 139+x11Colour PowderBlue = opaque $ sRGB24 176 224 230+x11Colour Purple = opaque $ sRGB24 160 32 240+x11Colour Purple1 = opaque $ sRGB24 155 48 255+x11Colour Purple2 = opaque $ sRGB24 145 44 238+x11Colour Purple3 = opaque $ sRGB24 125 38 205+x11Colour Purple4 = opaque $ sRGB24 85 26 139+x11Colour Red = opaque $ sRGB24 255 0 0+x11Colour Red1 = opaque $ sRGB24 255 0 0+x11Colour Red2 = opaque $ sRGB24 238 0 0+x11Colour Red3 = opaque $ sRGB24 205 0 0+x11Colour Red4 = opaque $ sRGB24 139 0 0+x11Colour RosyBrown = opaque $ sRGB24 188 143 143+x11Colour RosyBrown1 = opaque $ sRGB24 255 193 193+x11Colour RosyBrown2 = opaque $ sRGB24 238 180 180+x11Colour RosyBrown3 = opaque $ sRGB24 205 155 155+x11Colour RosyBrown4 = opaque $ sRGB24 139 105 105+x11Colour RoyalBlue = opaque $ sRGB24 65 105 225+x11Colour RoyalBlue1 = opaque $ sRGB24 72 118 255+x11Colour RoyalBlue2 = opaque $ sRGB24 67 110 238+x11Colour RoyalBlue3 = opaque $ sRGB24 58 95 205+x11Colour RoyalBlue4 = opaque $ sRGB24 39 64 139+x11Colour SaddleBrown = opaque $ sRGB24 139 69 19+x11Colour Salmon = opaque $ sRGB24 250 128 114+x11Colour Salmon1 = opaque $ sRGB24 255 140 105+x11Colour Salmon2 = opaque $ sRGB24 238 130 98+x11Colour Salmon3 = opaque $ sRGB24 205 112 84+x11Colour Salmon4 = opaque $ sRGB24 139 76 57+x11Colour SandyBrown = opaque $ sRGB24 244 164 96+x11Colour SeaGreen = opaque $ sRGB24 46 139 87+x11Colour SeaGreen1 = opaque $ sRGB24 84 255 159+x11Colour SeaGreen2 = opaque $ sRGB24 78 238 148+x11Colour SeaGreen3 = opaque $ sRGB24 67 205 128+x11Colour SeaGreen4 = opaque $ sRGB24 46 139 87+x11Colour SeaShell = opaque $ sRGB24 255 245 238+x11Colour SeaShell1 = opaque $ sRGB24 255 245 238+x11Colour SeaShell2 = opaque $ sRGB24 238 229 222+x11Colour SeaShell3 = opaque $ sRGB24 205 197 191+x11Colour SeaShell4 = opaque $ sRGB24 139 134 130+x11Colour Sienna = opaque $ sRGB24 160 82 45+x11Colour Sienna1 = opaque $ sRGB24 255 130 71+x11Colour Sienna2 = opaque $ sRGB24 238 121 66+x11Colour Sienna3 = opaque $ sRGB24 205 104 57+x11Colour Sienna4 = opaque $ sRGB24 139 71 38+x11Colour SkyBlue = opaque $ sRGB24 135 206 235+x11Colour SkyBlue1 = opaque $ sRGB24 135 206 255+x11Colour SkyBlue2 = opaque $ sRGB24 126 192 238+x11Colour SkyBlue3 = opaque $ sRGB24 108 166 205+x11Colour SkyBlue4 = opaque $ sRGB24 74 112 139+x11Colour SlateBlue = opaque $ sRGB24 106 90 205+x11Colour SlateBlue1 = opaque $ sRGB24 131 111 255+x11Colour SlateBlue2 = opaque $ sRGB24 122 103 238+x11Colour SlateBlue3 = opaque $ sRGB24 105 89 205+x11Colour SlateBlue4 = opaque $ sRGB24 71 60 139+x11Colour SlateGray = opaque $ sRGB24 112 128 144+x11Colour SlateGray1 = opaque $ sRGB24 198 226 255+x11Colour SlateGray2 = opaque $ sRGB24 185 211 238+x11Colour SlateGray3 = opaque $ sRGB24 159 182 205+x11Colour SlateGray4 = opaque $ sRGB24 108 123 139+x11Colour Snow = opaque $ sRGB24 255 250 250+x11Colour Snow1 = opaque $ sRGB24 255 250 250+x11Colour Snow2 = opaque $ sRGB24 238 233 233+x11Colour Snow3 = opaque $ sRGB24 205 201 201+x11Colour Snow4 = opaque $ sRGB24 139 137 137+x11Colour SpringGreen = opaque $ sRGB24 0 255 127+x11Colour SpringGreen1 = opaque $ sRGB24 0 255 127+x11Colour SpringGreen2 = opaque $ sRGB24 0 238 118+x11Colour SpringGreen3 = opaque $ sRGB24 0 205 102+x11Colour SpringGreen4 = opaque $ sRGB24 0 139 69+x11Colour SteelBlue = opaque $ sRGB24 70 130 180+x11Colour SteelBlue1 = opaque $ sRGB24 99 184 255+x11Colour SteelBlue2 = opaque $ sRGB24 92 172 238+x11Colour SteelBlue3 = opaque $ sRGB24 79 148 205+x11Colour SteelBlue4 = opaque $ sRGB24 54 100 139+x11Colour Tan = opaque $ sRGB24 210 180 140+x11Colour Tan1 = opaque $ sRGB24 255 165 79+x11Colour Tan2 = opaque $ sRGB24 238 154 73+x11Colour Tan3 = opaque $ sRGB24 205 133 63+x11Colour Tan4 = opaque $ sRGB24 139 90 43+x11Colour Thistle = opaque $ sRGB24 216 191 216+x11Colour Thistle1 = opaque $ sRGB24 255 225 255+x11Colour Thistle2 = opaque $ sRGB24 238 210 238+x11Colour Thistle3 = opaque $ sRGB24 205 181 205+x11Colour Thistle4 = opaque $ sRGB24 139 123 139+x11Colour Tomato = opaque $ sRGB24 255 99 71+x11Colour Tomato1 = opaque $ sRGB24 255 99 71+x11Colour Tomato2 = opaque $ sRGB24 238 92 66+x11Colour Tomato3 = opaque $ sRGB24 205 79 57+x11Colour Tomato4 = opaque $ sRGB24 139 54 38+x11Colour Transparent = transparent+x11Colour Turquoise = opaque $ sRGB24 64 224 208+x11Colour Turquoise1 = opaque $ sRGB24 0 245 255+x11Colour Turquoise2 = opaque $ sRGB24 0 229 238+x11Colour Turquoise3 = opaque $ sRGB24 0 197 205+x11Colour Turquoise4 = opaque $ sRGB24 0 134 139+x11Colour Violet = opaque $ sRGB24 238 130 238+x11Colour VioletRed = opaque $ sRGB24 208 32 144+x11Colour VioletRed1 = opaque $ sRGB24 255 62 150+x11Colour VioletRed2 = opaque $ sRGB24 238 58 140+x11Colour VioletRed3 = opaque $ sRGB24 205 50 120+x11Colour VioletRed4 = opaque $ sRGB24 139 34 82+x11Colour Wheat = opaque $ sRGB24 245 222 179+x11Colour Wheat1 = opaque $ sRGB24 255 231 186+x11Colour Wheat2 = opaque $ sRGB24 238 216 174+x11Colour Wheat3 = opaque $ sRGB24 205 186 150+x11Colour Wheat4 = opaque $ sRGB24 139 126 102+x11Colour White = opaque $ sRGB24 255 255 255+x11Colour WhiteSmoke = opaque $ sRGB24 245 245 245+x11Colour Yellow = opaque $ sRGB24 255 255 0+x11Colour Yellow1 = opaque $ sRGB24 255 255 0+x11Colour Yellow2 = opaque $ sRGB24 238 238 0+x11Colour Yellow3 = opaque $ sRGB24 205 205 0+x11Colour Yellow4 = opaque $ sRGB24 139 139 0+x11Colour YellowGreen = opaque $ sRGB24 154 205 50++-- | Convert a 'Colour' value to an 'RGB' 'Color'.+fromColour :: Colour Double -> Color+fromColour = uncurryRGB RGB . toSRGB24++-- | Convert an 'AlphaColour' to an 'RGBA' 'Color'. The exception to+-- this is for any 'AlphaColour' which has @alphaChannel ac == 0@;+-- these are converted to @X11Color 'Transparent'@ (note that the+-- 'Show' instance for such an 'AlphaColour' is @\"transparent\"@).+fromAColour :: AlphaColour Double -> Color+fromAColour ac+ | a == 0 = X11Color Transparent+ | otherwise = rgb $ round a'+ where+ a = alphaChannel ac+ a' = a * maxWord+ rgb = uncurryRGB RGBA $ toSRGB24 colour+ colour = darken (recip a) (ac `over` black)++-- | The 'maxBound' of a 'Word8' value.+maxWord :: Double+maxWord = fromIntegral (maxBound :: Word8)
Data/GraphViz/Commands.hs view
@@ -1,50 +1,87 @@ {- | Module : Data.GraphViz.Commands- Description : Functions to run GraphViz commands.+ Description : Functions to run Graphviz commands. Copyright : (c) Matthew Sackman, Ivan Lazar Miljenovic License : 3-Clause BSD-style Maintainer : Ivan.Miljenovic@gmail.com - This module defines functions to call the various GraphViz- commands.-- Most of these functions were from version 0.5 of /Graphalyze/:+ This module defines functions to call the various Graphviz+ commands. It is based upon code originally written for version 0.5+ of /Graphalyze/:+ <http://hackage.haskell.org/cgi-bin/hackage-scripts/package/Graphalyze-0.5> - <http://hackage.haskell.org/cgi-bin/hackage-scripts/package/Graphalyze-0.5>+ Whilst various output formats are supported (see 'GraphvizOutput'+ for a complete list), it is not yet possible to choose a desired+ renderer and formatter. Being able to determine which renderers+ and formatters are applicable for a specific 'GraphvizOutput' is+ not easy (there is no listing of available renderers or formatters+ on the Graphviz website), and for the most part the default ones do+ the job well. -}- module Data.GraphViz.Commands- ( GraphvizCommand(..)+ ( -- * The different Graphviz tools available.+ GraphvizCommand(..) , dirCommand , undirCommand , commandFor+ -- * The possible outputs that Graphviz supports.+ -- $outputs , GraphvizOutput(..)+ , GraphvizCanvas(..)+ -- * Running Graphviz.+ , RunResult(..) , runGraphviz , runGraphvizCommand+ , addExtension+ , runGraphvizCanvas+ , runGraphvizCanvas' , graphvizWithHandle- )- where+ -- * Helper utilities.+ , hGetContents'+ ) where -import System.IO-import System.Exit-import System.Process-import Data.Array.IO-import Control.Concurrent-import Control.Exception.Extensible+-- Want to use the extensible-exception version+import Prelude hiding (catch) import Data.GraphViz.Types import Data.GraphViz.Types.Printing+-- This is here just for Haddock linking purposes.+import Data.GraphViz.Attributes(Attribute(Z)) --- | The available Graphviz commands.-data GraphvizCommand = Dot | Neato | TwoPi | Circo | Fdp+import qualified Data.ByteString as B+import System.IO( Handle, hClose, hPutStr+ , hGetContents, hSetBinaryMode)+import System.Exit(ExitCode(ExitSuccess))+import System.Process(runInteractiveProcess, waitForProcess)+import Control.Concurrent(MVar, forkIO, newEmptyMVar, putMVar, takeMVar)+import Control.Exception.Extensible( SomeException(..), catch+ , bracket, evaluate, handle)+import Control.Monad(liftM)+import System.FilePath(FilePath, (<.>)) -instance Show GraphvizCommand where- show Dot = "dot"- show Neato = "neato"- show TwoPi = "twopi"- show Circo = "circo"- show Fdp = "fdp"+-- ----------------------------------------------------------------------------- +-- | The available Graphviz commands. The following directions are+-- based upon those in the Graphviz man page (available online at+-- <http://graphviz.org/pdf/dot.1.pdf>, or if installed on your+-- system @man graphviz@). Note that any command can be used on+-- both directed and undirected graphs.+data GraphvizCommand = Dot -- ^ For hierachical graphs (ideal for+ -- directed graphs).+ | Neato -- ^ For symmetric layouts of graphs+ -- (ideal for undirected graphs).+ | TwoPi -- ^ For radial layout of graphs.+ | Circo -- ^ For circular layout of graphs.+ | Fdp -- ^ For symmetric layout of graphs.+ deriving (Eq, Ord, Show, Read)++showCmd :: GraphvizCommand -> String+showCmd Dot = "dot"+showCmd Neato = "neato"+showCmd TwoPi = "twopi"+showCmd Circo = "circo"+showCmd Fdp = "fdp"+ -- | The default command for directed graphs. dirCommand :: GraphvizCommand dirCommand = Dot@@ -53,169 +90,312 @@ undirCommand :: GraphvizCommand undirCommand = Neato --- | The appropriate (default) GraphViz command for the given graph.+-- | The appropriate (default) Graphviz command for the given graph. commandFor :: DotGraph a -> GraphvizCommand-commandFor dg = if (directedGraph dg)+commandFor dg = if directedGraph dg then dirCommand else undirCommand --- | The possible Graphviz outputs, obtained by running /dot -Txxx/.--- 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. For now, more--- information is available from:--- <http://graphviz.org/doc/info/output.html>-data GraphvizOutput = Canon- | Cmap- | Cmapx- | Cmapx_np- | Dia- | DotOutput- | Eps- | Fig- | Gd- | Gd2- | Gif- | Gtk- | Hpgl- | Imap- | Imap_np- | Ismap- | Jpe- | Jpeg- | Jpg- | Mif- | Mp- | Pcl- | Pdf- | Pic- | Plain- | PlainExt- | Png- | Ps- | Ps2- | Svg- | Svgz- | Tk- | Vml- | Vmlz- | Vrml- | Vtx- | Wbmp- | Xdot- | Xlib+-- ----------------------------------------------------------------------------- -instance Show GraphvizOutput where- show Canon = "canon"- show Cmap = "cmap"- show Cmapx = "cmapx"- show Cmapx_np = "cmapx_np"- show Dia = "dia"- show DotOutput = "dot"- show Eps = "eps"- show Fig = "fig"- show Gd = "gd"- show Gd2 = "gd2"- show Gif = "gif"- show Gtk = "gtk"- show Hpgl = "hpgl"- show Imap = "imap"- show Imap_np = "imap_np"- show Ismap = "ismap"- show Jpe = "jpe"- show Jpeg = "jpeg"- show Jpg = "jpg"- show Mif = "mif"- show Mp = "mp"- show Pcl = "pcl"- show Pdf = "pdf"- show Pic = "pic"- show Plain = "plain"- show PlainExt = "plain-ext"- show Png = "png"- show Ps = "ps"- show Ps2 = "ps2"- show Svg = "svg"- show Svgz = "svgz"- show Tk = "tk"- show Vml = "vml"- show Vmlz = "vmlz"- show Vrml = "vrml"- show Vtx = "vtx"- show Wbmp = "wbmp"- show Xdot = "xdot"- show Xlib = "xlib"+{- $outputs + The list of output types supported by Graphviz is dependent upon+ how it is built on your system. To determine which actual formats+ are available on your system, run @dot -T?@. Trying to use an+ output type that is not supported by your installation of Graphviz+ will result in an error.++ The outputs defined here in 'GraphvizOutput' and 'GraphvizCanvas'+ are those from the default list of available outputs. For more+ information, see:+ <http://graphviz.org/doc/info/output.html>++-}++-- | This class is for those data types that are valid options for the+-- Graphviz tools to use with the @-T@ argument.+class GraphvizResult o where+ outputCall :: o -> String+ isBinary :: o -> Bool++-- | The possible Graphviz output formats (that is, those that+-- actually produce a file).+data GraphvizOutput = Bmp -- ^ Windows Bitmap Format.+ | Canon -- ^ Pretty-printed Dot output with no+ -- layout performed.+ | DotOutput -- ^ Reproduces the input along with+ -- layout information.+ | XDot -- ^ As with 'DotOutput', but provides+ -- even more information on how the+ -- graph is drawn.+ | Eps -- ^ Encapsulated PostScript.+ | Fig -- ^ FIG graphics language.+ | Gd -- ^ Internal GD library format.+ | Gd2 -- ^ Compressed version of 'Gd'.+ | Gif -- ^ Graphics Interchange Format.+ | Ico -- ^ Icon image file format.+ | Imap -- ^ Server-side imagemap.+ | Cmapx -- ^ Client-side imagemap.+ | ImapNP -- ^ As for 'Imap', except only+ -- rectangles are used as active+ -- areas.+ | CmapxNP -- ^ As for 'Cmapx', except only+ -- rectangles are used as active+ -- areas.+ | Jpeg -- ^ The JPEG image format.+ | Pdf -- ^ Portable Document Format.+ | Plain -- ^ Simple text format.+ | PlainExt -- ^ As for 'Plain', but provides port+ -- names on head and tail nodes when+ -- applicable.+ | Png -- ^ Portable Network Graphvics format.+ | Ps -- ^ PostScript.+ | Ps2 -- ^ PostScript for PDF.+ | Svg -- ^ Scalable Vector Graphics format.+ | SvgZ -- ^ Compressed SVG format.+ | Tiff -- ^ Tagged Image File Format.+ | Vml -- ^ Vector Markup Language; 'Svg' is+ -- usually preferred.+ | VmlZ -- ^ Compressed VML format; 'SvgZ' is+ -- usually preferred.+ | Vrml -- ^ Virtual Reality Modeling Language+ -- format; requires nodes to have a+ -- 'Z' attribute.+ | WBmp -- ^ Wireless BitMap format;+ -- monochrome format usually used+ -- for mobile computing devices.+ deriving (Eq, Ord, Show, Read)++instance GraphvizResult GraphvizOutput where+ outputCall Bmp = "bmp"+ outputCall Canon = "canon"+ outputCall DotOutput = "dot"+ outputCall XDot = "xdot"+ outputCall Eps = "eps"+ outputCall Fig = "fig"+ outputCall Gd = "gd"+ outputCall Gd2 = "gd2"+ outputCall Gif = "gif"+ outputCall Ico = "ico"+ outputCall Imap = "imap"+ outputCall Cmapx = "cmapx"+ outputCall ImapNP = "imap_np"+ outputCall CmapxNP = "cmapx_np"+ outputCall Jpeg = "jpeg"+ outputCall Pdf = "pdf"+ outputCall Plain = "plain"+ outputCall PlainExt = "plain-ext"+ outputCall Png = "png"+ outputCall Ps = "ps"+ outputCall Ps2 = "ps2"+ outputCall Svg = "svg"+ outputCall SvgZ = "svgz"+ outputCall Tiff = "tiff"+ outputCall Vml = "vml"+ outputCall VmlZ = "vmlz"+ outputCall Vrml = "vrml"+ outputCall WBmp = "wbmp"++ -- These are the known text-based outputs.+ isBinary Canon = False+ isBinary DotOutput = False+ isBinary XDot = False+ isBinary Eps = False+ isBinary Fig = False+ isBinary Imap = False+ isBinary Cmapx = False+ isBinary ImapNP = False+ isBinary CmapxNP = False+ isBinary Plain = False+ isBinary PlainExt = False+ isBinary Ps = False+ isBinary Svg = False+ isBinary Vml = False+ isBinary Vrml = False+ isBinary _ = True++-- | A default file extension for each 'GraphvizOutput'.+defaultExtension :: GraphvizOutput -> String+defaultExtension Bmp = "bmp"+defaultExtension Canon = "dot"+defaultExtension DotOutput = "dot"+defaultExtension XDot = "dot"+defaultExtension Eps = "eps"+defaultExtension Fig = "fig"+defaultExtension Gd = "gd"+defaultExtension Gd2 = "gd2"+defaultExtension Gif = "gif"+defaultExtension Ico = "ico"+defaultExtension Imap = "map"+defaultExtension Cmapx = "map"+defaultExtension ImapNP = "map"+defaultExtension CmapxNP = "map"+defaultExtension Jpeg = "jpg"+defaultExtension Pdf = "pdf"+defaultExtension Plain = "txt"+defaultExtension PlainExt = "txt"+defaultExtension Png = "png"+defaultExtension Ps = "ps"+defaultExtension Ps2 = "ps"+defaultExtension Svg = "svg"+defaultExtension SvgZ = "svgz"+defaultExtension Tiff = "tif"+defaultExtension Vml = "vml"+defaultExtension VmlZ = "vmlz"+defaultExtension Vrml = "vrml"+defaultExtension WBmp = "wbmp"++-- | Unlike 'GraphvizOutput', these items do not produce an output+-- file; instead, they directly draw a canvas (i.e. a window) with+-- the resulting image.+data GraphvizCanvas = Gtk | Xlib+ deriving (Eq, Ord, Read, Show)++instance GraphvizResult GraphvizCanvas where+ outputCall Gtk = "gtk"+ outputCall Xlib = "xlib"++ -- Since there's no output, we arbitrarily choose binary mode.+ isBinary _ = True++-- -----------------------------------------------------------------------------++-- | Represents the result of running a command.+data RunResult = Error String+ | Success+ deriving (Eq, Ord, Read, Show)++-- | Return the error if there is one, otherwise return Success.+maybeErr :: Either String a -> RunResult+maybeErr = either Error (const Success)+ -- | Run the recommended Graphviz command on this graph, saving the result -- to the file provided (note: file extensions are /not/ checked).--- Returns @True@ if successful, @False@ otherwise.-runGraphviz :: (PrintDot n) => DotGraph n -> GraphvizOutput -> FilePath- -> IO Bool-runGraphviz gr t fp = runGraphvizCommand (commandFor gr) gr t fp+runGraphviz :: (PrintDot n) => DotGraph n -> GraphvizOutput -> FilePath+ -> IO RunResult+runGraphviz gr = runGraphvizCommand (commandFor gr) gr -- | Run the chosen Graphviz command on this graph, saving the result -- to the file provided (note: file extensions are /not/ checked).--- Returns @True@ if successful, @False@ otherwise. runGraphvizCommand :: (PrintDot n) => GraphvizCommand -> DotGraph n- -> GraphvizOutput -> FilePath -> IO Bool-runGraphvizCommand cmd gr t fp- = do pipe <- tryJust (\(SomeException _) -> return ())- $ openFile fp WriteMode- case pipe of- (Left _) -> return False- (Right f) -> do file <- graphvizWithHandle cmd gr t (toFile f)- case file of- (Just _) -> return True- _ -> return False- where- toFile f h = do squirt h f- hClose h- hClose f+ -> GraphvizOutput -> FilePath -> IO RunResult+runGraphvizCommand cmd gr t fp+ = liftM maybeErr+ $ graphvizWithHandle cmd gr t toFile+ where+ toFile h = B.hGetContents h >>= B.writeFile fp --- graphvizWithHandle sometimes throws an error about handles not--- being closed properly: investigate (now on the official TODO).+-- | Append the default extension for the provided 'GraphvizOutput' to+-- the provided 'FilePath' for the output file.+addExtension :: (GraphvizOutput -> FilePath -> IO a)+ -> GraphvizOutput -> FilePath -> IO a+addExtension cmd t fp = cmd t fp'+ where+ fp' = fp <.> defaultExtension t -- | Run the chosen Graphviz command on this graph, but send the--- result to the given handle rather than to a file. The @'Handle'--- -> 'IO' a@ function should close the 'Handle' once it is--- finished.+-- result to the given handle rather than to a file. ----- The result is wrapped in 'Maybe' rather than throwing an error.-graphvizWithHandle :: (PrintDot n, Show a) => GraphvizCommand -> DotGraph n- -> GraphvizOutput -> (Handle -> IO a) -> IO (Maybe a)-graphvizWithHandle cmd gr t f- = do (inp, outp, errp, prc) <- runInteractiveCommand command- forkIO $ hPutStrLn inp (printDotGraph gr) >> hClose inp- forkIO $ (hGetContents errp >>= hPutStr stderr >> hClose errp)- a <- f outp- exitCode <- waitForProcess prc- case exitCode of- ExitSuccess -> return (Just a)- _ -> return Nothing+-- Note that the @'Handle' -> 'IO' a@ function /must/ fully consume+-- the input from the 'Handle'; 'hGetContents'' is an version of+-- 'hGetContents' that will ensure this happens.+--+-- If the command was unsuccessful, then @Left error@ is returned.+graphvizWithHandle :: (PrintDot n, Show a)+ => GraphvizCommand -- ^ Which command to run+ -> DotGraph n -- ^ The 'DotGraph' to use+ -> GraphvizOutput -- ^ The 'GraphvizOutput' type+ -> (Handle -> IO a) -- ^ Extract the output+ -> IO (Either String a) -- ^ The error or the result.+graphvizWithHandle = graphvizWithHandle'++-- This version is not exported as we don't want to let arbitrary+-- @Handle -> IO a@ functions to be used for GraphvizCanvas outputs.+graphvizWithHandle' :: (PrintDot n, GraphvizResult o, Show a)+ => GraphvizCommand -> DotGraph n -> o+ -> (Handle -> IO a) -> IO (Either String a)+graphvizWithHandle' cmd gr t f+ = handle notRunnable+ $ bracket+ (runInteractiveProcess cmd' args Nothing Nothing)+ (\(inh,outh,errh,_) -> hClose inh >> hClose outh >> hClose errh)+ $ \(inp,outp,errp,prc) -> do++ -- The input and error are text, not binary+ hSetBinaryMode inp False+ hSetBinaryMode errp False+ hSetBinaryMode outp $ isBinary t -- Depends on output type++ -- Make sure we close the input or it will hang!!!!!!!+ forkIO $ hPutStr inp (printDotGraph gr) >> hClose inp++ -- Need to make sure both the output and error handles are+ -- really fully consumed.+ mvOutput <- newEmptyMVar+ mvErr <- newEmptyMVar++ _ <- forkIO $ signalWhenDone hGetContents' errp mvErr+ _ <- forkIO $ signalWhenDone f' outp mvOutput++ -- When these are both able to be taken, then the forks are finished+ err <- takeMVar mvErr+ output <- takeMVar mvOutput++ exitCode <- waitForProcess prc++ case exitCode of+ ExitSuccess -> return output+ _ -> return $ Left $ othErr ++ err where- command = (show cmd) ++ " -T" ++ (show t)+ notRunnable e@SomeException{} = return . Left $ unwords+ [ "Unable to call the Graphviz command "+ , cmd'+ , " with the arguments: "+ , unwords args+ , " because of: "+ , show e+ ]+ cmd' = showCmd cmd+ args = ["-T" ++ outputCall t] -{- |- This function is taken from the /mohws/ project, available under a- 3-Clause BSD license. The actual function is taken from:- <http://code.haskell.org/mohws/src/Util.hs>- It provides an efficient way of transferring data from one 'Handle'- to another.- -}-squirt :: Handle -> Handle -> IO ()-squirt rd wr = do- arr <- newArray_ (0, bufsize-1)- let loop = do- r <- hGetArray rd arr bufsize- if (r == 0)- then return ()- else if (r < bufsize)- then hPutArray wr arr r- else hPutArray wr arr bufsize >> loop- loop+ -- Augmenting the f function to let it work within the forkIO:+ f' h = liftM Right (f h)+ `catch`+ (\e@SomeException{} -> return . Left $ fErr ++ show e)+ fErr = "Error re-directing the output from " ++ cmd' ++ ": "++ othErr = "Error messages from " ++ cmd' ++ ":\n"++-- | Store the result of the 'Handle' consumption into the 'MVar'.+signalWhenDone :: (Handle -> IO a) -> Handle -> MVar a -> IO ()+signalWhenDone f h mv = f h >>= putMVar mv >> return ()++-- | Run the chosen Graphviz command on this graph and render it using+-- the given canvas type.+runGraphvizCanvas :: (PrintDot n) => GraphvizCommand -> DotGraph n+ -> GraphvizCanvas -> IO RunResult+runGraphvizCanvas cmd gr c = liftM maybeErr+ $ graphvizWithHandle' cmd gr c nullHandle where- -- This was originally separate- bufsize :: Int- bufsize = 4 * 1024+ nullHandle :: Handle -> IO ()+ nullHandle h = do r <- hGetContents h+ evaluate (length r)+ return () +-- | Run the recommended Graphviz command on this graph and render it+-- using the given canvas type.+runGraphvizCanvas' :: (PrintDot n) => DotGraph n -> GraphvizCanvas+ -> IO RunResult+runGraphvizCanvas' d = runGraphvizCanvas (commandFor d) d++-- -----------------------------------------------------------------------------+-- Utility functions++-- | A version of 'hGetContents' that fully evaluates the contents of+-- the 'Handle' (that is, until EOF is reached). The 'Handle' is+-- not closed.+hGetContents' :: Handle -> IO String+hGetContents' h = do r <- hGetContents h+ evaluate $ length r+ return r
+ Data/GraphViz/Testing.hs view
@@ -0,0 +1,238 @@+{- |+ Module : Data.GraphViz.Testing+ Description : Test-suite for graphviz.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This defines a test-suite for the graphviz library.++ Limitations of the test suite are as follows:++ * For the most part, this library lets you use arbitrary numbers+ for String values. However, this is not tested due to too many+ corner cases for special parsers that don't take arbitrary+ Strings. As the Dot standard is ambiguous over whether you can+ or can't use numbers as Strings (more specifically, if they+ should be quoted or not), this is a user beware situation.++ * Same goes for empty Strings; sometimes they're allowed, sometimes+ they're not. Thus, to simplify matters they're not generated.++ * The generated Strings are very simple, only composed of lower+ case letters, digits and some symbols. This is because too many+ tests were "failing" due to some corner case; e.g. lower-case+ letters only because the parser parses Strings as lowercase, so+ if a particular String isn't valid (e.g. @\"all\"@ for 'LayerID',+ then the 'Arbitrary' instance has to ensure that all possible+ ways of capitalising that String isn't generated as a random+ 'LRName'.++ * The generated 'DotGraph's are not guaranteed to be valid; as+ such, the 'prop_parsePrettyID' property is not able to be tested+ as dot, etc. choke on invalid Dot code.++ * To avoid needless endless recursion, 'DotSubGraph's do not have+ sub-'DotSubGraph's.++ * The 'Graph' values that are generated do not have multiple edges,+ as the 'prop_dotizeAugment' property uses 'dotize'', which makes+ no guarantees on what will happen for 'Graph's with multiple+ edges.++ * This test suite isn't perfect: if you deliberately try to stuff+ something up, you probably can.+-}+module Data.GraphViz.Testing+ ( -- * Running the test suite.+ runDefaultTests+ -- ** The tests themselves+ , Test(..)+ , test_printParseID_Attributes+ , test_printParseID+ , test_preProcessingID+ , test_parsePrettyID+ , test_dotizeAugment+ -- * Re-exporting modules for manual testing.+ , module Data.GraphViz+ , module Data.GraphViz.Testing.Properties+ , printIt+ , parseIt+ , preProcess+ ) where++import Test.QuickCheck++import Data.GraphViz.Testing.Instances()+-- This module cannot be re-exported from Instances, as it causes+-- Overlapping Instances.+import Data.GraphViz.Testing.Instances.FGL()+import Data.GraphViz.Testing.Properties++import Data.GraphViz hiding (RunResult(..))+import Data.GraphViz.Types.Parsing(parseIt, preProcess)+import Data.GraphViz.Types.Printing(printIt)+-- Can't use PatriciaTree because a Show instance is needed.+import Data.Graph.Inductive.Tree(Gr)++import System.Exit(ExitCode(..), exitWith)+import System.IO(hPutStrLn, stderr)++-- -----------------------------------------------------------------------------++runDefaultTests :: IO ()+runDefaultTests = do putStrLn msg+ blankLn+ runTests defaultTests+ spacerLn+ putStrLn successMsg+ where+ msg = "This is the test suite for the graphviz library.\n\+ \If any of these tests fail, please inform the maintainer,\n\+ \including full output of this test suite.\n\+ \\n\+ \This test suite takes approximately 90 minutes to run on a\n\+ \2 GHz Mobile Core 2 Duo (running with a single thread)."++ successMsg = "All tests were successful!"+++-- -----------------------------------------------------------------------------+-- Defining a Test structure and how to run tests.++-- | Defines the test structure being used.+data Test = Test { name :: String+ , desc :: String+ , test :: IO Result -- ^ QuickCheck test.+ }++-- | Run all of the provided tests.+runTests :: [Test] -> IO ()+runTests = mapM_ ((>>) spacerLn . runTest)++-- | Run the provided test.+runTest :: Test -> IO ()+runTest tst = do putStrLn title+ blankLn+ putStrLn $ desc tst+ blankLn+ r <- test tst+ blankLn+ case r of+ Success{} -> putStrLn successMsg+ GaveUp{} -> putStrLn gaveUpMsg+ _ -> die failMsg+ blankLn+ where+ nm = '"' : name tst ++ "\""+ title = "Running test: " ++ nm ++ "."+ successMsg = "All tests for " ++ nm ++ " were successful!"+ gaveUpMsg = "Too many sample inputs for " ++ nm ++ " were rejected;\n\+ \tentatively marking this as successful."+ failMsg = "The tests for " ++ nm ++ " failed!\n\+ \Not attempting any further tests."++spacerLn :: IO ()+spacerLn = putStrLn (replicate 70 '=') >> blankLn++blankLn :: IO ()+blankLn = putStrLn ""++die :: String -> IO a+die msg = do hPutStrLn stderr msg+ exitWith (ExitFailure 1)++-- -----------------------------------------------------------------------------+-- Defining the tests to use.++-- | The tests to run by default.+defaultTests :: [Test]+defaultTests = [ test_printParseID_Attributes+ , test_printParseID+ , test_preProcessingID+ -- Can't run this test, since we don't generate valid+ -- DotGraphs to pass to Graphviz!+ -- , test_parsePrettyID+ , test_dotizeAugment+ ]++-- | Test that 'Attributes' can be printed and then parsed back.+test_printParseID_Attributes :: Test+test_printParseID_Attributes+ = Test { name = "Printing and parsing of Attributes"+ , desc = dsc+ , test = quickCheckWithResult args prop+ }+ where+ prop :: Attributes -> Property+ prop = prop_printParseListID++ args = stdArgs { maxSuccess = numGen }+ numGen = 10000+ defGen = maxSuccess stdArgs++ dsc = "The most common source of errors in printing and parsing are for\n\+ \Attributes. As such, these are stress-tested before we run the\n\+ \rest of the tests, generating " ++ show numGen ++ " lists of\n\+ \Attributes rather than the default " ++ show defGen ++ " tests."++test_printParseID :: Test+test_printParseID+ = Test { name = "Printing and Parsing DotGraphs"+ , desc = dsc+ , test = quickCheckResult prop+ }+ where+ prop :: DotGraph Int -> Bool+ prop = prop_printParseID++ dsc = "The graphviz library should be able to parse back in its own\n\+ \generated Dot code. This test aims to determine the validity\n\+ \of this for the overall \"DotGraph Int\" values."++test_preProcessingID :: Test+test_preProcessingID+ = Test { name = "Pre-processing Dot code"+ , desc = dsc+ , test = quickCheckResult prop+ }+ where+ prop :: DotGraph Int -> Bool+ prop = prop_preProcessingID++ dsc = "When parsing Dot code, some pre-processing is done to remove items\n\+ \such as comments and to join together multi-line strings. This\n\+ \test verifies that this pre-processing doesn't affect actual\n\+ \Dot code by running the pre-processor on generated Dot code."++-- | This test is not valid for use until valid DotGraphs can be generated.+test_parsePrettyID :: Test+test_parsePrettyID+ = Test { name = "Parsing pretty-printed code"+ , desc = dsc+ , test = quickCheckResult prop+ }+ where+ prop :: DotGraph Int -> Bool+ prop = prop_parsePrettyID++ dsc = "By default, the graphviz library doesn't produce readable Dot\n\+ \code to ensure that lines aren't truncated, etc. This test\n\+ \ensures that the pretty-printing functions produce Dot code\n\+ \that is still parseable (which should also help ensure that\n\+ \ \"Real-World\" Dot code is also parseable)."++test_dotizeAugment :: Test+test_dotizeAugment+ = Test { name = "Augmenting FGL Graphs"+ , desc = dsc+ , test = quickCheckResult prop+ }+ where+ prop :: Gr Char Double -> Bool+ prop = prop_dotizeAugment++ dsc = "The various Graph to Graph functions in Data.GraphViz should\n\+ \only _augment_ the graph labels and not change the graphs\n\+ \themselves. This test compares the original graphs to these\n\+ \augmented graphs and verifies that they are the same."
+ Data/GraphViz/Testing/Instances.hs view
@@ -0,0 +1,847 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++{- |+ Module : Data.GraphViz.Testing.Instances+ Description : 'Arbitrary' instances for graphviz.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module defines the 'Arbitrary' instances for the various types+ used to represent Graphviz Dot code.++ Note that they do not generally generate /sensible/ values for the+ various types; in particular, there's no guarantee that the+ 'Attributes' chosen for a particular value type are indeed legal+ for that type.+-}+module Data.GraphViz.Testing.Instances() where++import Data.GraphViz.Types.Parsing(isNumString)++import Data.GraphViz.Attributes+import Data.GraphViz.Types++import Test.QuickCheck++import Data.Char(toLower)+import Data.List(nub)+import Control.Monad(liftM, liftM2, liftM3, liftM4, guard)+import Data.Word(Word8)++-- -----------------------------------------------------------------------------+-- Defining Arbitrary instances for the overall types++instance (Eq a, Arbitrary a) => Arbitrary (DotGraph a) where+ arbitrary = liftM4 DotGraph arbitrary arbitrary arbitrary arbitrary++ shrink (DotGraph str dir gid stmts) = map (DotGraph str dir gid)+ $ shrink stmts++instance Arbitrary GraphID where+ arbitrary = oneof [ liftM Str arbString+ , liftM Int arbitrary+ , liftM Dbl $ suchThat arbitrary notInt+ , liftM HTML arbitrary+ ]++ shrink (Str s) = map Str $ shrinkString s+ shrink (Int i) = map Int $ shrink i+ shrink (Dbl d) = map Dbl $ filter notInt $ shrink d+ shrink (HTML u) = map HTML $ shrink u++instance (Eq a, Arbitrary a) => Arbitrary (DotStatements a) where+ arbitrary = arbDS True++ shrink ds@(DotStmts gas sgs ns es) = do gas' <- shrinkL gas+ sgs' <- shrinkL sgs+ ns' <- shrinkL ns+ es' <- shrinkL es+ returnCheck ds+ $ DotStmts gas' sgs' ns' es'++-- | If 'True', generate 'DotSubGraph's; otherwise don't.+arbDS :: (Arbitrary a, Eq a) => Bool -> Gen (DotStatements a)+arbDS haveSGs = liftM4 DotStmts arbitrary genSGs arbitrary arbitrary+ where+ genSGs = if haveSGs+ then resize 2 arbitrary+ else return []++instance Arbitrary GlobalAttributes where+ arbitrary = oneof [ liftM GraphAttrs arbList+ , liftM NodeAttrs arbList+ , liftM EdgeAttrs arbList+ ]++ shrink (GraphAttrs atts) = map GraphAttrs $ nonEmptyShrinks atts+ shrink (NodeAttrs atts) = map NodeAttrs $ nonEmptyShrinks atts+ shrink (EdgeAttrs atts) = map EdgeAttrs $ nonEmptyShrinks atts++instance (Eq a, Arbitrary a) => Arbitrary (DotSubGraph a) where+ arbitrary = liftM3 DotSG arbitrary arbitrary (arbDS False)++ shrink (DotSG isCl mid stmts) = map (DotSG isCl mid) $ shrink stmts++instance (Arbitrary a) => Arbitrary (DotNode a) where+ arbitrary = liftM2 DotNode arbitrary arbitrary++ shrink (DotNode n as) = map (DotNode n) $ shrinkList as++instance (Arbitrary a) => Arbitrary (DotEdge a) where+ arbitrary = liftM4 DotEdge arbitrary arbitrary arbitrary arbitrary++ shrink (DotEdge f t isDir as) = map (DotEdge f t isDir) $ shrinkList as++-- -----------------------------------------------------------------------------+-- Defining Arbitrary instances for Attributes++instance Arbitrary Attribute where+ arbitrary = oneof [ liftM Damping arbitrary+ , liftM K arbitrary+ , liftM URL arbitrary+ , liftM ArrowHead arbitrary+ , liftM ArrowSize arbitrary+ , liftM ArrowTail arbitrary+ , liftM Aspect arbitrary+ , liftM Bb arbitrary+ , liftM BgColor arbitrary+ , liftM Center arbitrary+ , liftM Charset arbString+ , liftM ClusterRank arbitrary+ , liftM ColorScheme arbitrary+ , liftM Color arbList+ , liftM Comment arbString+ , liftM Compound arbitrary+ , liftM Concentrate arbitrary+ , liftM Constraint arbitrary+ , liftM Decorate arbitrary+ , liftM DefaultDist arbitrary+ , liftM Dimen arbitrary+ , liftM Dim arbitrary+ , liftM Dir arbitrary+ , liftM DirEdgeConstraints arbitrary+ , liftM Distortion arbitrary+ , liftM DPI arbitrary+ , liftM EdgeURL arbitrary+ , liftM EdgeTarget arbString+ , liftM EdgeTooltip arbString+ , liftM Epsilon arbitrary+ , liftM ESep arbitrary+ , liftM FillColor arbitrary+ , liftM FixedSize arbitrary+ , liftM FontColor arbitrary+ , liftM FontName arbString+ , liftM FontNames arbString+ , liftM FontPath arbString+ , liftM FontSize arbitrary+ , liftM Group arbString+ , liftM HeadURL arbitrary+ , liftM HeadClip arbitrary+ , liftM HeadLabel arbitrary+ , liftM HeadPort arbitrary+ , liftM HeadTarget arbString+ , liftM HeadTooltip arbString+ , liftM Height arbitrary+ , liftM ID arbitrary+ , liftM Image arbString+ , liftM ImageScale arbitrary+ , liftM LabelURL arbitrary+ , liftM LabelAngle arbitrary+ , liftM LabelDistance arbitrary+ , liftM LabelFloat arbitrary+ , liftM LabelFontColor arbitrary+ , liftM LabelFontName arbString+ , liftM LabelFontSize arbitrary+ , liftM LabelJust arbitrary+ , liftM LabelLoc arbitrary+ , liftM LabelTarget arbString+ , liftM LabelTooltip arbString+ , liftM Label arbitrary+ , liftM Landscape arbitrary+ , liftM LayerSep arbString+ , liftM Layers arbitrary+ , liftM Layer arbitrary+ , liftM Layout arbString+ , liftM Len arbitrary+ , liftM LevelsGap arbitrary+ , liftM Levels arbitrary+ , liftM LHead arbString+ , liftM LPos arbitrary+ , liftM LTail arbString+ , liftM Margin arbitrary+ , liftM MaxIter arbitrary+ , liftM MCLimit arbitrary+ , liftM MinDist arbitrary+ , liftM MinLen arbitrary+ , liftM Model arbitrary+ , liftM Mode arbitrary+ , liftM Mosek arbitrary+ , liftM NodeSep arbitrary+ , liftM NoJustify arbitrary+ , liftM Normalize arbitrary+ , liftM Nslimit1 arbitrary+ , liftM Nslimit arbitrary+ , liftM Ordering arbString+ , liftM Orientation arbitrary+ , liftM OutputOrder arbitrary+ , liftM OverlapScaling arbitrary+ , liftM Overlap arbitrary+ , liftM PackMode arbitrary+ , liftM Pack arbitrary+ , liftM Pad arbitrary+ , liftM PageDir arbitrary+ , liftM Page arbitrary+ , liftM PenColor arbitrary+ , liftM PenWidth arbitrary+ , liftM Peripheries arbitrary+ , liftM Pin arbitrary+ , liftM Pos arbitrary+ , liftM QuadTree arbitrary+ , liftM Quantum arbitrary+ , liftM RankDir arbitrary+ , liftM RankSep arbitrary+ , liftM Rank arbitrary+ , liftM Ratio arbitrary+ , liftM Rects arbitrary+ , liftM Regular arbitrary+ , liftM ReMinCross arbitrary+ , liftM RepulsiveForce arbitrary+ , liftM Root arbitrary+ , liftM Rotate arbitrary+ , liftM SameHead arbString+ , liftM SameTail arbString+ , liftM SamplePoints arbitrary+ , liftM SearchSize arbitrary+ , liftM Sep arbitrary+ , liftM ShapeFile arbString+ , liftM Shape arbitrary+ , liftM ShowBoxes arbitrary+ , liftM Sides arbitrary+ , liftM Size arbitrary+ , liftM Skew arbitrary+ , liftM Smoothing arbitrary+ , liftM SortV arbitrary+ , liftM Splines arbitrary+ , liftM Start arbitrary+ , liftM StyleSheet arbString+ , liftM Style arbList+ , liftM TailURL arbitrary+ , liftM TailClip arbitrary+ , liftM TailLabel arbitrary+ , liftM TailPort arbitrary+ , liftM TailTarget arbString+ , liftM TailTooltip arbString+ , liftM Target arbString+ , liftM Tooltip arbString+ , liftM TrueColor arbitrary+ , liftM Vertices arbList+ , liftM ViewPort arbitrary+ , liftM VoroMargin arbitrary+ , liftM Weight arbitrary+ , liftM Width arbitrary+ , liftM Z arbitrary+ ]++ shrink (Damping v) = map Damping $ shrink v+ shrink (K v) = map K $ shrink v+ shrink (URL v) = map URL $ shrink v+ shrink (ArrowHead v) = map ArrowHead $ shrink v+ shrink (ArrowSize v) = map ArrowSize $ shrink v+ shrink (ArrowTail v) = map ArrowTail $ shrink v+ shrink (Aspect v) = map Aspect $ shrink v+ shrink (Bb v) = map Bb $ shrink v+ shrink (BgColor v) = map BgColor $ shrink v+ shrink (Center v) = map Center $ shrink v+ shrink (Charset v) = map Charset $ shrinkString v+ shrink (ClusterRank v) = map ClusterRank $ shrink v+ shrink (ColorScheme v) = map ColorScheme $ shrink v+ shrink (Color v) = map Color $ nonEmptyShrinks v+ shrink (Comment v) = map Comment $ shrinkString v+ shrink (Compound v) = map Compound $ shrink v+ shrink (Concentrate v) = map Concentrate $ shrink v+ shrink (Constraint v) = map Constraint $ shrink v+ shrink (Decorate v) = map Decorate $ shrink v+ shrink (DefaultDist v) = map DefaultDist $ shrink v+ shrink (Dimen v) = map Dimen $ shrink v+ shrink (Dim v) = map Dim $ shrink v+ shrink (Dir v) = map Dir $ shrink v+ shrink (DirEdgeConstraints v) = map DirEdgeConstraints $ shrink v+ shrink (Distortion v) = map Distortion $ shrink v+ shrink (DPI v) = map DPI $ shrink v+ shrink (EdgeURL v) = map EdgeURL $ shrink v+ shrink (EdgeTarget v) = map EdgeTarget $ shrinkString v+ shrink (EdgeTooltip v) = map EdgeTooltip $ shrinkString v+ shrink (Epsilon v) = map Epsilon $ shrink v+ shrink (ESep v) = map ESep $ shrink v+ shrink (FillColor v) = map FillColor $ shrink v+ shrink (FixedSize v) = map FixedSize $ shrink v+ shrink (FontColor v) = map FontColor $ shrink v+ shrink (FontName v) = map FontName $ shrinkString v+ shrink (FontNames v) = map FontNames $ shrinkString v+ shrink (FontPath v) = map FontPath $ shrinkString v+ shrink (FontSize v) = map FontSize $ shrink v+ shrink (Group v) = map Group $ shrinkString v+ shrink (HeadURL v) = map HeadURL $ shrink v+ shrink (HeadClip v) = map HeadClip $ shrink v+ shrink (HeadLabel v) = map HeadLabel $ shrink v+ shrink (HeadPort v) = map HeadPort $ shrink v+ shrink (HeadTarget v) = map HeadTarget $ shrinkString v+ shrink (HeadTooltip v) = map HeadTooltip $ shrinkString v+ shrink (Height v) = map Height $ shrink v+ shrink (ID v) = map ID $ shrink v+ shrink (Image v) = map Image $ shrinkString v+ shrink (ImageScale v) = map ImageScale $ shrink v+ shrink (LabelURL v) = map LabelURL $ shrink v+ shrink (LabelAngle v) = map LabelAngle $ shrink v+ shrink (LabelDistance v) = map LabelDistance $ shrink v+ shrink (LabelFloat v) = map LabelFloat $ shrink v+ shrink (LabelFontColor v) = map LabelFontColor $ shrink v+ shrink (LabelFontName v) = map LabelFontName $ shrinkString v+ shrink (LabelFontSize v) = map LabelFontSize $ shrink v+ shrink (LabelJust v) = map LabelJust $ shrink v+ shrink (LabelLoc v) = map LabelLoc $ shrink v+ shrink (LabelTarget v) = map LabelTarget $ shrinkString v+ shrink (LabelTooltip v) = map LabelTooltip $ shrinkString v+ shrink (Label v) = map Label $ shrink v+ shrink (Landscape v) = map Landscape $ shrink v+ shrink (LayerSep v) = map LayerSep $ shrinkString v+ shrink (Layers v) = map Layers $ shrink v+ shrink (Layer v) = map Layer $ shrink v+ shrink (Layout v) = map Layout $ shrinkString v+ shrink (Len v) = map Len $ shrink v+ shrink (LevelsGap v) = map LevelsGap $ shrink v+ shrink (Levels v) = map Levels $ shrink v+ shrink (LHead v) = map LHead $ shrinkString v+ shrink (LPos v) = map LPos $ shrink v+ shrink (LTail v) = map LTail $ shrinkString v+ shrink (Margin v) = map Margin $ shrink v+ shrink (MaxIter v) = map MaxIter $ shrink v+ shrink (MCLimit v) = map MCLimit $ shrink v+ shrink (MinDist v) = map MinDist $ shrink v+ shrink (MinLen v) = map MinLen $ shrink v+ shrink (Model v) = map Model $ shrink v+ shrink (Mode v) = map Mode $ shrink v+ shrink (Mosek v) = map Mosek $ shrink v+ shrink (NodeSep v) = map NodeSep $ shrink v+ shrink (NoJustify v) = map NoJustify $ shrink v+ shrink (Normalize v) = map Normalize $ shrink v+ shrink (Nslimit1 v) = map Nslimit1 $ shrink v+ shrink (Nslimit v) = map Nslimit $ shrink v+ shrink (Ordering v) = map Ordering $ shrinkString v+ shrink (Orientation v) = map Orientation $ shrink v+ shrink (OutputOrder v) = map OutputOrder $ shrink v+ shrink (OverlapScaling v) = map OverlapScaling $ shrink v+ shrink (Overlap v) = map Overlap $ shrink v+ shrink (PackMode v) = map PackMode $ shrink v+ shrink (Pack v) = map Pack $ shrink v+ shrink (Pad v) = map Pad $ shrink v+ shrink (PageDir v) = map PageDir $ shrink v+ shrink (Page v) = map Page $ shrink v+ shrink (PenColor v) = map PenColor $ shrink v+ shrink (PenWidth v) = map PenWidth $ shrink v+ shrink (Peripheries v) = map Peripheries $ shrink v+ shrink (Pin v) = map Pin $ shrink v+ shrink (Pos v) = map Pos $ shrink v+ shrink (QuadTree v) = map QuadTree $ shrink v+ shrink (Quantum v) = map Quantum $ shrink v+ shrink (RankDir v) = map RankDir $ shrink v+ shrink (RankSep v) = map RankSep $ shrink v+ shrink (Rank v) = map Rank $ shrink v+ shrink (Ratio v) = map Ratio $ shrink v+ shrink (Rects v) = map Rects $ shrink v+ shrink (Regular v) = map Regular $ shrink v+ shrink (ReMinCross v) = map ReMinCross $ shrink v+ shrink (RepulsiveForce v) = map RepulsiveForce $ shrink v+ shrink (Root v) = map Root $ shrink v+ shrink (Rotate v) = map Rotate $ shrink v+ shrink (SameHead v) = map SameHead $ shrinkString v+ shrink (SameTail v) = map SameTail $ shrinkString v+ shrink (SamplePoints v) = map SamplePoints $ shrink v+ shrink (SearchSize v) = map SearchSize $ shrink v+ shrink (Sep v) = map Sep $ shrink v+ shrink (ShapeFile v) = map ShapeFile $ shrinkString v+ shrink (Shape v) = map Shape $ shrink v+ shrink (ShowBoxes v) = map ShowBoxes $ shrink v+ shrink (Sides v) = map Sides $ shrink v+ shrink (Size v) = map Size $ shrink v+ shrink (Skew v) = map Skew $ shrink v+ shrink (Smoothing v) = map Smoothing $ shrink v+ shrink (SortV v) = map SortV $ shrink v+ shrink (Splines v) = map Splines $ shrink v+ shrink (Start v) = map Start $ shrink v+ shrink (StyleSheet v) = map StyleSheet $ shrinkString v+ shrink (Style v) = map Style $ nonEmptyShrinks v+ shrink (TailURL v) = map TailURL $ shrink v+ shrink (TailClip v) = map TailClip $ shrink v+ shrink (TailLabel v) = map TailLabel $ shrink v+ shrink (TailPort v) = map TailPort $ shrink v+ shrink (TailTarget v) = map TailTarget $ shrinkString v+ shrink (TailTooltip v) = map TailTooltip $ shrinkString v+ shrink (Target v) = map Target $ shrinkString v+ shrink (Tooltip v) = map Tooltip $ shrinkString v+ shrink (TrueColor v) = map TrueColor $ shrink v+ shrink (Vertices v) = map Vertices $ nonEmptyShrinks v+ shrink (ViewPort v) = map ViewPort $ shrink v+ shrink (VoroMargin v) = map VoroMargin $ shrink v+ shrink (Weight v) = map Weight $ shrink v+ shrink (Width v) = map Width $ shrink v+ shrink (Z v) = map Z $ shrink v+{- delete to here -}++instance Arbitrary Word8 where+ arbitrary = arbitraryBoundedIntegral+ shrink = shrinkIntegral++instance Arbitrary URL where+ arbitrary = liftM UStr+ $ suchThat arbString (not . null)++ shrink (UStr ustr) = map UStr $ nonEmptyShrinks ustr++instance Arbitrary ArrowType where+ arbitrary = liftM AType+ -- Arrow specifications have between 1 and 4 elements.+ $ resize 4 arbList++ shrink (AType as) = map AType $ nonEmptyShrinks as++instance Arbitrary ArrowShape where+ arbitrary = arbBounded++instance Arbitrary ArrowModifier where+ arbitrary = liftM2 ArrMod arbitrary arbitrary++instance Arbitrary ArrowFill where+ arbitrary = arbBounded++instance Arbitrary ArrowSide where+ arbitrary = arbBounded++instance Arbitrary AspectType where+ arbitrary = oneof [ liftM RatioOnly arbitrary+ , liftM2 RatioPassCount arbitrary posArbitrary+ ]++ shrink (RatioOnly d) = map RatioOnly $ shrink d+ shrink (RatioPassCount d i) = do ds <- shrink d+ is <- shrink i+ return $ RatioPassCount ds is++instance Arbitrary Rect where+ arbitrary = liftM2 Rect arbitrary arbitrary++ shrink (Rect p1 p2) = do p1s <- shrink p1+ p2s <- shrink p2+ return $ Rect p1s p2s++instance Arbitrary Point where+ -- Pretty sure points have to be positive...+ arbitrary = oneof [ liftM2 Point posArbitrary posArbitrary+ , liftM (uncurry PointD)+ $ suchThat (liftM2 (,) posArbitrary posArbitrary)+ notBothInt+ ]++ shrink (Point v1 v2) = do v1s <- shrink v1+ v2s <- shrink v2+ return $ Point v1s v2s+ shrink (PointD v1 v2) = do v1s <- shrink v1+ v2s <- shrink v2+ guard $ notBothInt (v1s,v2s)+ return $ PointD v1s v2s++instance Arbitrary ClusterMode where+ arbitrary = arbBounded++instance Arbitrary DirType where+ arbitrary = arbBounded++instance Arbitrary DEConstraints where+ arbitrary = arbBounded++instance Arbitrary DPoint where+ arbitrary = oneof [ liftM DVal arbitrary+ , liftM PVal arbitrary+ ]++ shrink (DVal d) = map DVal $ shrink d+ shrink (PVal p) = map PVal $ shrink p++instance Arbitrary ModeType where+ arbitrary = arbBounded++instance Arbitrary Model where+ arbitrary = arbBounded++instance Arbitrary Label where+ arbitrary = oneof [ liftM StrLabel arbString+ , liftM URLLabel arbitrary+ ]++ shrink (StrLabel str) = map StrLabel $ shrinkString str+ shrink (URLLabel url) = map URLLabel $ shrink url++instance Arbitrary Overlap where+ arbitrary = oneof [ simpleOverlap+ , liftM PrismOverlap arbitrary+ ]+ where+ -- Have to do this by hand since Overlap can't have Bounded and+ -- Enum instances+ simpleOverlap = elements [ KeepOverlaps+ , RemoveOverlaps+ , ScaleOverlaps+ , ScaleXYOverlaps+ , CompressOverlap+ , VpscOverlap+ , IpsepOverlap+ ]++ shrink (PrismOverlap mi) = map PrismOverlap $ shrink mi+ shrink _ = []++instance Arbitrary LayerList where+ arbitrary = do fs <- arbLayerName+ oths <- listOf $ liftM2 (,) arbLayerSep arbLayerName+ return $ LL fs oths++ -- This should be improved to try actually shrinking the seps and names.+ -- shrink (LL _ [(_,fs')]) = [LL fs' []]+ -- shrink (LL fs oths) = map (LL fs) $ shrink oths++instance Arbitrary LayerRange where+ arbitrary = oneof [ liftM LRID arbitrary+ , liftM3 LRS arbitrary arbLayerSep arbitrary+ ]++ shrink (LRID nm) = map LRID $ shrink nm+ shrink (LRS l1 _ l2) = [LRID l1, LRID l2]++instance Arbitrary LayerID where+ arbitrary = oneof [ return AllLayers+ , liftM LRInt arbitrary+ , liftM LRName $ suchThat arbLayerName lrnameCheck+ ]++ shrink AllLayers = []+ shrink (LRInt i) = map LRInt $ shrink i+ shrink (LRName nm) = map LRName+ . filter lrnameCheck+ $ shrinkString nm++lrnameCheck :: String -> Bool+lrnameCheck = (/=) "all"++instance Arbitrary OutputMode where+ arbitrary = arbBounded++instance Arbitrary Pack where+ arbitrary = oneof [ return DoPack+ , return DontPack+ , liftM PackMargin arbitrary+ ]++ shrink (PackMargin m) = map PackMargin $ shrink m+ shrink _ = []++instance Arbitrary PackMode where+ arbitrary = oneof [ return PackNode+ , return PackClust+ , return PackGraph+ , liftM3 PackArray arbitrary arbitrary arbitrary+ ]++ shrink (PackArray c u mi) = map (PackArray c u) $ shrink mi+ shrink _ = []++instance Arbitrary Pos where+ arbitrary = oneof [ liftM PointPos arbitrary+ -- A single spline with only one point overall+ -- is just a point...+ , liftM SplinePos $ suchThat arbList validSplineList+ ]+ where++ shrink (PointPos p) = map PointPos $ shrink p+ shrink (SplinePos ss) = map SplinePos . filter validSplineList+ $ nonEmptyShrinks ss++validSplineList :: [Spline] -> Bool+validSplineList [Spline Nothing Nothing [_]] = False+validSplineList _ = True++instance Arbitrary Spline where+ arbitrary = liftM3 Spline arbitrary arbitrary+ -- list of points must have length of 1 mod 3+ $ suchThat arbitrary ((==) 1 . flip mod 3 . length)++ shrink (Spline Nothing Nothing [p]) = map (Spline Nothing Nothing . return)+ $ shrink p+ -- We're not going to be shrinking the points in the list; just+ -- making sure that its length is === 1 mod 3+ shrink (Spline ms me ps) = do mss <- shrinkM ms+ mes <- shrinkM me+ pss <- rem2 ps+ return $ Spline mss mes pss+ where++ rem1 [] = []+ rem1 (a:as) = as : map (a:) (rem1 as)++ rem2 = nub . concatMap rem1 . rem1++instance Arbitrary EdgeType where+ arbitrary = arbBounded++instance Arbitrary PageDir where+ arbitrary = arbBounded++instance Arbitrary QuadType where+ arbitrary = arbBounded++instance Arbitrary Root where+ arbitrary = oneof [ return IsCentral+ , return NotCentral+ , liftM NodeName arbString+ ]++ shrink (NodeName nm) = map NodeName $ shrinkString nm+ shrink _ = []++instance Arbitrary RankType where+ arbitrary = arbBounded++instance Arbitrary RankDir where+ arbitrary = arbBounded++instance Arbitrary Shape where+ arbitrary = arbBounded++instance Arbitrary SmoothType where+ arbitrary = arbBounded++instance Arbitrary StartType where+ arbitrary = oneof [ liftM StartStyle arbitrary+ , liftM StartSeed arbitrary+ , liftM2 StartStyleSeed arbitrary arbitrary+ ]++ shrink StartStyle{} = [] -- No shrinks for STStyle+ shrink (StartSeed ss) = map StartSeed $ shrink ss+ shrink (StartStyleSeed st ss) = map (StartStyleSeed st) $ shrink ss++instance Arbitrary STStyle where+ arbitrary = arbBounded++instance Arbitrary StyleItem where+ arbitrary = liftM2 SItem arbitrary (listOf arbStyleName)++ -- Can't use this because of what shrink on the individual strings+ -- might do.+ -- shrink (SItem sn opts) = map (SItem sn) $ shrink opts++instance Arbitrary StyleName where+ arbitrary = oneof [ defaultStyles+ , liftM DD $ suchThat arbStyleName notDefault+ ]+ where+ defaultStyles = elements [ Dashed+ , Dotted+ , Bold+ , Invisible+ , Filled+ , Diagonals+ , Rounded+ ]+ notDefault = flip notElem [ "dashed"+ , "dotted"+ , "solid"+ , "bold"+ , "invis"+ , "filled"+ , "diagonals"+ , "rounded"+ ]++instance Arbitrary PortPos where+ arbitrary = liftM PP arbitrary++instance Arbitrary CompassPoint where+ arbitrary = arbBounded++instance Arbitrary ViewPort where+ arbitrary = liftM4 VP arbitrary arbitrary arbitrary arbitrary++ shrink (VP w h z f) = case sVPs of+ [_] -> []+ _ -> sVPs+ where+ sVPs = do ws <- shrink w+ hs <- shrink h+ zs <- shrink z+ fs <- shrinkM f+ return $ VP ws hs zs fs++instance Arbitrary FocusType where+ arbitrary = oneof [ liftM XY arbitrary+ , liftM NodeFocus $ suchThat arbString (all ((/=) ','))+ ]++ shrink (XY p) = map XY $ shrink p+ shrink (NodeFocus str) = map NodeFocus $ shrinkString str++instance Arbitrary VerticalPlacement where+ arbitrary = arbBounded++instance Arbitrary ScaleType where+ arbitrary = arbBounded++instance Arbitrary Justification where+ arbitrary = arbBounded++instance Arbitrary Ratios where+ arbitrary = oneof [ liftM AspectRatio posArbitrary+ , namedRats+ ]+ where+ namedRats = elements [ FillRatio+ , CompressRatio+ , ExpandRatio+ , AutoRatio+ ]++ shrink (AspectRatio r) = map (AspectRatio . fromPositive)+ . shrink $ Positive r+ shrink _ = []++instance Arbitrary ColorScheme where+ arbitrary = oneof [ return X11+ , liftM2 BrewerScheme arbitrary arbitrary+ ]++ shrink (BrewerScheme nm v) = map (BrewerScheme nm) $ shrink v+ shrink _ = []++instance Arbitrary BrewerName where+ arbitrary = arbBounded++instance Arbitrary Color where+ arbitrary = oneof [ liftM3 RGB arbitrary arbitrary arbitrary+ , liftM4 RGBA arbitrary arbitrary arbitrary arbitrary+ , liftM3 HSV zeroOne zeroOne zeroOne+ , liftM X11Color arbitrary+ -- Not quite right as the values can get too+ -- high/low, but should suffice for+ -- printing/parsing purposes.+ , liftM BrewerColor arbitrary+ ]+ where+ zeroOne = choose (0,1)++ shrink (RGB r g b) = do rs <- shrink r+ gs <- shrink g+ bs <- shrink b+ return $ RGB rs gs bs+ shrink (RGBA r g b a) = RGB r g b+ : do rs <- shrink r+ gs <- shrink g+ bs <- shrink b+ as <- shrink a+ return $ RGBA rs gs bs as+ shrink (BrewerColor c) = map BrewerColor $ shrink c+ shrink _ = [] -- Shrinking 0<=h,s,v<=1 does nothing++instance Arbitrary X11Color where+ arbitrary = arbBounded++-- -----------------------------------------------------------------------------+-- Helper Functions++fromPositive :: Positive a -> a+fromPositive (Positive a) = a++posArbitrary :: (Arbitrary a, Num a, Ord a) => Gen a+posArbitrary = liftM fromPositive arbitrary++arbString :: Gen String+arbString = suchThat (liftM (map toLower) genStr) validString+ where+ genStr = listOf1 $ elements strChr+ strChr = ['a'..'z'] ++ ['0'..'9'] ++ ['\'', '"', ' ', '\t', '(', ')'+ , ',', ':', '.']+validString :: String -> Bool+validString "true" = False+validString "false" = False+validString str = notNumStr str++shrinkString :: String -> [String]+shrinkString = filter validString . nonEmptyShrinks++notNumStr :: String -> Bool+notNumStr = not . isNumString++arbBounded :: (Bounded a, Enum a) => Gen a+arbBounded = elements [minBound .. maxBound]++arbLayerSep :: Gen [Char]+arbLayerSep = listOf1 (elements defLayerSep)++arbLayerName :: Gen String+arbLayerName = suchThat arbString (all notLayerSep)++arbStyleName :: Gen String+arbStyleName = suchThat arbString (all notBrackCom)+ where+ notBrackCom = flip notElem ['(', ')', ',', ' ']++arbList :: (Arbitrary a) => Gen [a]+arbList = listOf1 arbitrary++nonEmptyShrinks :: (Arbitrary a) => [a] -> [[a]]+nonEmptyShrinks = filter (not . null) . shrinkList++-- Shrink lists with more than one value only by removing values, not+-- by shrinking individual items.+shrinkList :: (Arbitrary a) => [a] -> [[a]]+shrinkList [a] = map return $ shrink a+shrinkList as = rm (length as) as+ where+ rm 0 _ = []+ rm 1 _ = [[]]+ rm n xs = xs1+ : xs2+ : ( [ xs1' ++ xs2 | xs1' <- rm n1 xs1, not (null xs1') ]+ `ilv` [ xs1 ++ xs2' | xs2' <- rm n2 xs2, not (null xs2') ]+ )+ where+ n1 = n `div` 2+ xs1 = take n1 xs+ n2 = n - n1+ xs2 = drop n1 xs++ [] `ilv` ys = ys+ xs `ilv` [] = xs+ (x:xs) `ilv` (y:ys) = x : y : (xs `ilv` ys)++-- When a Maybe value is a sub-component, and we need shrink to return+-- a value.+shrinkM :: (Arbitrary a) => Maybe a -> [Maybe a]+shrinkM Nothing = [Nothing]+shrinkM j = shrink j++shrinkL :: (Arbitrary a) => [a] -> [[a]]+shrinkL xs = case shrinkList xs of+ [] -> [xs]+ xs' -> xs'++notInt :: Double -> Bool+notInt d = fromIntegral (round d :: Int) /= d++notBothInt :: (Double, Double) -> Bool+notBothInt (p1,p2) = notInt p1 && notInt p2++returnCheck :: (Eq a) => a -> a -> [a]+returnCheck o n = if o == n+ then []+ else [n]
+ Data/GraphViz/Testing/Instances/FGL.hs view
@@ -0,0 +1,42 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE FlexibleInstances #-}++{- |+ Module : Data.GraphViz.Testing.Instances.FGL+ Description : 'Arbitrary' instances for FGL graphs.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module defines the 'Arbitrary' instances for FGL 'DynGraph'+ graphs. Note that this instance cannot be in+ "Data.GraphViz.Testing.Instances", as this instance requires the+ FlexibleInstances extension, which makes some of the other+ 'Arbitrary' instances fail to type-check.+-}+module Data.GraphViz.Testing.Instances.FGL() where++import Test.QuickCheck++import Data.Graph.Inductive.Graph(Graph, mkGraph, nodes, delNode)+import Data.Function(on)+import Data.List(group, sort, nubBy)+import Control.Monad(liftM, liftM3)++-- -----------------------------------------------------------------------------+-- Arbitrary instance for FGL graphs.++instance (Graph g, Arbitrary n, Arbitrary e) => Arbitrary (g n e) where+ arbitrary = do ns <- suchThat genNs (not . null)+ let nGen = elements ns+ lns <- mapM makeLNode ns+ les <- liftM filtEs . listOf $ makeLEdge nGen+ return $ mkGraph lns les+ where+ genNs = liftM (map head . group . sort) arbitrary+ filtEs = nubBy ((==) `on` toE)+ toE (f,t,_) = (f,t)+ makeLNode n = liftM ((,) n) arbitrary+ makeLEdge nGen = liftM3 (,,) nGen nGen arbitrary++ shrink gr = map (flip delNode gr) (nodes gr)
+ Data/GraphViz/Testing/Properties.hs view
@@ -0,0 +1,68 @@+{- |+ Module : Data.GraphViz.Testing.Properties+ Description : Properties for testing.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ Various properties that should hold true for the graphviz library.+-}+module Data.GraphViz.Testing.Properties where++import Data.GraphViz(dotizeGraph', prettyPrint')+import Data.GraphViz.Types(DotGraph, printDotGraph)+import Data.GraphViz.Types.Printing(PrintDot(..), printIt)+import Data.GraphViz.Types.Parsing(ParseDot(..), parseIt, preProcess)++import Test.QuickCheck++import Data.Graph.Inductive(DynGraph, equal, nmap, emap)++-- -----------------------------------------------------------------------------+-- The properties to test for++-- | Checking that @parse . print == id@; that is, graphviz can parse+-- its own output.+prop_printParseID :: (ParseDot a, PrintDot a, Eq a) => a -> Bool+prop_printParseID a = fst (tryParse a) == a++-- | A version of 'prop_printParse' specifically for lists; it ensures+-- that the list is not empty (as most list-based parsers fail on+-- empty lists).+prop_printParseListID :: (ParseDot a, PrintDot a, Eq a) => [a] -> Property+prop_printParseListID as = not (null as) ==> prop_printParseID as++-- | Pre-processing shouldn't change the output of printed Dot code.+-- This should work for all 'PrintDot' instances, but is more+-- specific to 'DotGraph' values.+prop_preProcessingID :: (PrintDot a) => DotGraph a -> Bool+prop_preProcessingID dg = preProcess dotCode == dotCode+ where+ dotCode = printDotGraph dg++-- | This is a version of 'prop_printParseID' that tries to parse the+-- pretty-printed output of 'prettyPrint'' rather than just 'printIt'.+prop_parsePrettyID :: (Eq a, ParseDot a, PrintDot a) => DotGraph a -> Bool+prop_parsePrettyID dg = (fst . parseIt . prettyPrint') dg == dg++-- | This property verifies that 'dotize'', etc. only /augment/ the+-- original graph; that is, the actual nodes, edges and labels for+-- each remain unchanged. Whilst 'dotize'', etc. only require+-- 'Graph' instances, this property requires 'DynGraph' (which is a+-- sub-class of 'Graph') instances to be able to strip off the+-- 'Attributes' augmentations.+prop_dotizeAugment :: (DynGraph g, Eq n, Ord e) => g n e -> Bool+prop_dotizeAugment g = equal g (unAugment g')+ where+ g' = dotizeGraph' g+ unAugment = nmap snd . emap snd++-- -----------------------------------------------------------------------------+-- Helper utility functions++-- | A utility function to use for debugging purposes for trying to+-- find how graphviz /is/ parsing something. This is easier than+-- using @'parseIt' . 'printIt'@ directly, since it avoids having to+-- enter and explicit type signature.+tryParse :: (ParseDot a, PrintDot a) => a -> (a, String)+tryParse = parseIt . printIt
Data/GraphViz/Types.hs view
@@ -1,12 +1,12 @@ {- | Module : Data.GraphViz.Types- Description : Definition of the GraphViz types.+ Description : Definition of the Graphviz types. Copyright : (c) Matthew Sackman, Ivan Lazar Miljenovic License : 3-Clause BSD-style Maintainer : Ivan.Miljenovic@gmail.com This module defines the overall types and methods that interact- with them for the GraphViz library. The specifications are based+ with them for the Graphviz library. The specifications are based loosely upon the information available at: <http://graphviz.org/doc/info/lang.html> @@ -20,13 +20,14 @@ * When creating 'GraphID' values for 'graphID' and 'subGraphID', you should ensure that none of them have the same printed value as one of the 'nodeID' values to avoid any possible problems.- Note that if the 'DotSubGraph' has @'isCluster' = 'True'@ then- this isn't a problem. * If you want any 'GlobalAttributes' in a 'DotSubGraph' and want them to only apply to that 'DotSubGraph', then you must ensure it does indeed have a valid 'GraphID'. + * All 'DotSubGraph's with @'isCluster' = 'True'@ /must/ have unique+ 'subGraphID' values.+ * If eventually outputting to a format such as SVG, then you should make sure that your 'DotGraph' has a 'graphID', as that is used as the title of the resulting image.@@ -35,7 +36,7 @@ should ensure that you use a relatively simple node type (that is, it only covers a single line, etc.). - * Also, whilst GraphViz allows you to mix the types used for nodes,+ * Also, whilst Graphviz allows you to mix the types used for nodes, this library requires\/assumes that they are all the same type. * 'DotEdge' defines an edge @(a, b)@ (with an edge going from @a@@@ -59,7 +60,7 @@ * Nodes cannot have Port values. * Cannot place items in an arbitrary order: in particular, this- means that it is not possible to use the normal GraphViz hack of+ means that it is not possible to use the normal Graphviz hack of having graph attributes that do not apply to subgraphs\/clusters by listing them /after/ the subgraphs\/clusters. @@ -100,7 +101,7 @@ import Data.GraphViz.Types.Printing import Data.Maybe(isJust)-import Control.Monad(liftM)+import Control.Monad(liftM, when) -- ----------------------------------------------------------------------------- @@ -110,7 +111,7 @@ , graphID :: Maybe GraphID , graphStatements :: DotStatements a }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) -- | A strict graph disallows multiple edges. makeStrict :: DotGraph a -> DotGraph a@@ -134,7 +135,7 @@ -- that @'parseDotGraph' . 'printDotGraph' == 'id'@ (this might not -- be true the other way around due to un-parseable components). printDotGraph :: (PrintDot a) => DotGraph a -> String-printDotGraph = renderDot . toDot+printDotGraph = printIt -- | Parse a limited subset of the Dot language to form a 'DotGraph' -- (that is, the caveats listed in "Data.GraphViz.Attributes" aside,@@ -142,7 +143,7 @@ -- -- Also removes any comments, etc. before parsing. parseDotGraph :: (ParseDot a) => String -> DotGraph a-parseDotGraph = fst . runParser parse . preprocess+parseDotGraph = fst . parseIt . preProcess -- | Check if all the 'Attribute's are being used correctly. isValidGraph :: DotGraph a -> Bool@@ -156,8 +157,8 @@ unqtDot = printStmtBased printGraphID graphStatements printGraphID :: (PrintDot a) => DotGraph a -> DotCode-printGraphID g = bool strGraph' empty (strictGraph g)- <+> bool dirGraph' undirGraph' (directedGraph g)+printGraphID g = bool empty strGraph' (strictGraph g)+ <+> bool undirGraph' dirGraph' (directedGraph g) <+> maybe empty toDot (graphID g) instance (ParseDot a) => ParseDot (DotGraph a) where@@ -174,7 +175,7 @@ `onFail` stringRep False undirGraph )- gID <- optional parse+ gID <- optional $ parseAndSpace parse return $ DotGraph str dir gID dirGraph :: String@@ -206,7 +207,7 @@ data DotError a = GraphError Attribute | NodeError (Maybe a) Attribute | EdgeError (Maybe (a,a)) Attribute- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) -- ----------------------------------------------------------------------------- @@ -218,7 +219,7 @@ | Int Int | Dbl Double | HTML URL- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot GraphID where unqtDot (Str str) = unqtDot str@@ -230,21 +231,23 @@ toDot gID = unqtDot gID instance ParseDot GraphID where- parseUnqt = oneOf [ liftM Str parseUnqt- , liftM Int parseUnqt- , liftM Dbl parseUnqt- , liftM HTML parseUnqt- ]+ parseUnqt = liftM HTML parseUnqt+ `onFail`+ liftM stringNum parseUnqt - parse = oneOf [ liftM Int parse- , liftM Dbl parse- , liftM HTML parse- -- Parse last so that quoted numbers are parsed as numbers.- , liftM Str parse- ]+ parse = liftM HTML parse+ `onFail`+ liftM stringNum parse `adjustErr`- (++ "Not a valid GraphID")+ (++ "\nNot a valid GraphID") +stringNum :: String -> GraphID+stringNum str = maybe checkDbl Int $ stringToInt str+ where+ checkDbl = if isNumString str+ then Dbl $ toDouble str+ else Str str+ -- ----------------------------------------------------------------------------- data DotStatements a = DotStmts { attrStmts :: [GlobalAttributes]@@ -252,7 +255,7 @@ , nodeStmts :: [DotNode a] , edgeStmts :: [DotEdge a] }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance (PrintDot a) => PrintDot (DotStatements a) where unqtDot stmts = vcat [ toDot $ attrStmts stmts@@ -340,7 +343,7 @@ data GlobalAttributes = GraphAttrs { attrs :: Attributes } | NodeAttrs { attrs :: Attributes } | EdgeAttrs { attrs :: Attributes }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance PrintDot GlobalAttributes where unqtDot = printAttrBased printGlobAttrType attrs@@ -397,7 +400,7 @@ , subGraphID :: Maybe GraphID , subGraphStmts :: DotStatements a }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance (PrintDot a) => PrintDot (DotSubGraph a) where unqtDot = printStmtBased printSubGraphID subGraphStmts@@ -411,16 +414,19 @@ <+> maybe cl dtID (subGraphID s) where isCl = isCluster s- cl = bool clust' empty isCl+ cl = bool empty clust' isCl dtID = printSGID isCl -- | Print the actual ID for a 'DotSubGraph'. printSGID :: Bool -> GraphID -> DotCode-printSGID isCl sID = bool addClust noClust isCl+printSGID isCl sID = bool noClust addClust isCl where noClust = toDot sID+ -- Have to manually render it as we need the un-quoted form. addClust = toDot . (++) clust . (:) '_'- . renderDot $ unqtDot sID+ . renderDot $ mkDot sID+ mkDot (Str str) = text str -- Quotes will be escaped later+ mkDot gid = unqtDot gid instance (ParseDot a) => ParseDot (DotSubGraph a) where parseUnqt = parseStmtBased parseSubGraphID@@ -435,21 +441,53 @@ parseSubGraphID :: Parse (DotStatements a -> DotSubGraph a) parseSubGraphID = do string sGraph- whitespace'- (isCl,sID) <- parseSGID- return $ DotSG isCl sID+ whitespace+ liftM (uncurry DotSG) parseSGID parseSGID :: Parse (Bool, Maybe GraphID)-parseSGID = do s <- parse- return (fst $ runParser pStr s)- `onFail`- liftM (flip (,) Nothing) checkCl+parseSGID = oneOf [ liftM getClustFrom $ parseAndSpace parse+ , return (False, Nothing)+ ] where- checkCl = liftM isJust $ optional (string clust)- pStr = do isCl <- checkCl `discard`optional (character '_')- sID <- parseUnqt- return (isCl, Just sID)+ -- If it's a String value, check to see if it's actually a+ -- cluster_Blah value; thus need to manually re-parse it.+ getClustFrom (Str str) = fst $ runParser pStr str+ getClustFrom gid = (False, Just gid) + checkCl = stringRep True clust+ pStr = do isCl <- checkCl+ `onFail`+ return False+ when isCl $ optional (character '_') >> return ()+ sID <- optional pID+ let sID' = if sID == emptyID+ then Nothing+ else sID+ return (isCl, sID')++ emptyID = Just $ Str ""++ -- For Strings, there are no more quotes to unescape, so consume+ -- what you can.+ pID = liftM HTML parseUnqt+ `onFail`+ liftM stringNum (many next)++{- This is a much nicer result, but unfortunately it doesn't work.+ The problem is that Graphviz decides that a subgraph is a cluster+ if the ID starts with "cluster" (no quotes); thus, we _have_ to do+ the double layer of parsing to get it to work :@++ do isCl <- stringRep True clust+ `onFail`+ return False+ sID <- optional $ do when isCl+ $ optional (character '_') >> return ()+ parseUnqt+ when (isCl || isJust sID) $ whitespace >> return ()+ return (isCl, sID)+-}+ sGraph :: String sGraph = "subgraph" @@ -468,7 +506,7 @@ invalidSubGraph :: DotSubGraph a -> [DotError a] invalidSubGraph sg = invalidStmts valFunc (subGraphStmts sg) where- valFunc = bool usedByClusters usedBySubGraphs (isCluster sg)+ valFunc = bool usedBySubGraphs usedByClusters (isCluster sg) subGraphNodes :: DotSubGraph a -> [DotNode a] subGraphNodes = statementNodes . subGraphStmts@@ -484,7 +522,7 @@ data DotNode a = DotNode { nodeID :: a , nodeAttributes :: Attributes }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance (PrintDot a) => PrintDot (DotNode a) where unqtDot = printAttrBased printNodeID nodeAttributes@@ -523,7 +561,7 @@ , directedEdge :: Bool , edgeAttributes :: Attributes }- deriving (Eq, Show, Read)+ deriving (Eq, Ord, Show, Read) instance (PrintDot a) => PrintDot (DotEdge a) where unqtDot = printAttrBased printEdgeID edgeAttributes@@ -534,7 +572,7 @@ printEdgeID :: (PrintDot a) => DotEdge a -> DotCode printEdgeID e = unqtDot (edgeFromNodeID e)- <+> bool dirEdge' undirEdge' (directedEdge e)+ <+> bool undirEdge' dirEdge' (directedEdge e) <+> unqtDot (edgeToNodeID e)
Data/GraphViz/Types/Clustering.hs view
@@ -2,7 +2,7 @@ {- | Module : Data.GraphViz.Types.Clustering- Description : Definition of the clustering types for GraphViz.+ Description : Definition of the clustering types for Graphviz. Copyright : (c) Matthew Sackman, Ivan Lazar Miljenovic License : 3-Clause BSD-style Maintainer : Ivan.Miljenovic@gmail.com
Data/GraphViz/Types/Internal.hs view
@@ -15,8 +15,10 @@ , toLower ) +import Data.Maybe(isJust) import qualified Data.Set as Set import Data.Set(Set)+import Control.Monad(liftM2) isIDString :: String -> Bool isIDString [] = True@@ -28,7 +30,7 @@ frstIDString c = any ($c) [ isAsciiUpper , isAsciiLower , (==) '_'- , \ x -> x >= '\200' && x <= '\377'+ , liftM2 (&&) (>= '\200') (<= '\377') ] -- | The rest of a non-quoted 'String' must match this.@@ -38,17 +40,54 @@ -- | Determine if this String represents a number. isNumString :: String -> Bool isNumString "" = False+isNumString "-" = False isNumString str = case str of ('-':str') -> go str' _ -> go str where- go [] = False- go cs = case dropWhile isDigit cs of- [] -> True- ('.':ds) -> not (null ds) && all isDigit ds- _ -> False+ go s = case span isDigit (map toLower s) of+ (ds@(_:_),[]) -> all isDigit ds+ ([],'.':[]) -> False+ ([],'.':d:ds) -> isDigit d && checkEs' ds+ (_,'.':ds) -> checkEs $ dropWhile isDigit ds+ ([],_) -> False+ (_,ds) -> checkEs ds+ checkEs' s = case break ((==) 'e') s of+ ([], _) -> False+ (ds,es) -> all isDigit ds && checkEs es+ checkEs [] = True+ checkEs ('e':ds) = isIntString ds+ checkEs _ = False --- | GraphViz requires double quotes to be explicitly escaped.+-- | This assumes that 'isNumString' is 'True'.+toDouble :: String -> Double+toDouble str = case str of+ ('-':str') -> read $ '-' : adj str'+ _ -> read $ adj str+ where+ adj s = (:) '0'+ $ case span ((==) '.') (map toLower s) of+ (ds@(_:_), '.':[]) -> ds ++ '.' : '0' : []+ (ds, '.':es@('e':_)) -> ds ++ '.' : '0' : es+ _ -> s++isIntString :: String -> Bool+isIntString = isJust . stringToInt++-- | Determine if this String represents an integer.+stringToInt :: String -> Maybe Int+stringToInt str = if isNum+ then Just (read str)+ else Nothing+ where+ isNum = case str of+ "" -> False+ ['-'] -> False+ ('-':num) -> isNum' num+ _ -> isNum' str+ isNum' = all isDigit++-- | Graphviz requires double quotes to be explicitly escaped. escapeQuotes :: String -> String escapeQuotes [] = [] escapeQuotes ('"':str) = '\\':'"': escapeQuotes str@@ -73,8 +112,8 @@ , "strict" ] --- | Fold over 'Bool's.+-- | Fold over 'Bool's; first param is for 'False', second for 'True'. bool :: a -> a -> Bool -> a-bool t f b = if b+bool f t b = if b then t else f
Data/GraphViz/Types/Parsing.hs view
@@ -9,7 +9,7 @@ "Text.ParserCombinators.Poly.Lazy". Note that the 'ParseDot' instances for 'Bool', etc. match those- specified for use with GraphViz (e.g. non-zero integers are+ 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@@ -24,9 +24,13 @@ -- * The ParseDot class. , Parse , ParseDot(..)+ , parseIt -- * Convenience parsing combinators.+ , onlyBool , stringBlock , numString+ , isNumString+ , isIntString , quotedString , parseAndSpace , string@@ -40,6 +44,8 @@ , optionalQuotedString , optionalQuoted , quotedParse+ , orQuote+ , quoteChar , newline , newline' , parseComma@@ -57,8 +63,8 @@ , commaSep' , stringRep , stringReps- -- * Pre-processing- , preprocess+ -- * Pre-processing of Dot code to remove comments, etc.+ , preProcess ) where import Data.GraphViz.Types.Internal@@ -70,9 +76,10 @@ , toLower ) import Data.Function(on)-import Data.Maybe(isJust, fromMaybe)+import Data.Maybe(isJust, fromMaybe, isNothing) import Data.Ratio((%))-import Control.Monad(liftM)+import Data.Word(Word8)+import Control.Monad(liftM, when) -- ----------------------------------------------------------------------------- -- Based off code from Text.Parse in the polyparse library@@ -95,21 +102,34 @@ parseList :: Parse [a] parseList = quotedParse parseUnqtList +-- | Parse the required value, returning also the rest of the input+-- 'String' that hasn't been parsed.+parseIt :: (ParseDot a) => String -> (a, String)+parseIt = runParser parse+ instance ParseDot Int where parseUnqt = parseInt' +instance ParseDot Word8 where+ parseUnqt = parseInt+ instance ParseDot Double where parseUnqt = parseFloat' instance ParseDot Bool where- parseUnqt = oneOf [ stringRep True "true"- , stringRep False "false"- , liftM (zero /=) parseInt'- ]+ parseUnqt = onlyBool+ `onFail`+ liftM (zero /=) parseInt' where zero :: Int zero = 0 +-- | Use this when you do not want numbers to be treated as 'Bool' values.+onlyBool :: Parse Bool+onlyBool = oneOf [ stringRep True "true"+ , stringRep False "false"+ ]+ instance ParseDot Char where -- Can't be a quote character. parseUnqt = satisfy ((/=) quoteChar)@@ -118,10 +138,10 @@ `onFail` quotedParse parseUnqt - parseUnqtList = oneOf [ numString- , stringBlock- , quotedString- ]+ -- Too many problems with using this within other parsers where+ -- using numString or stringBlock will cause a parse failure. As+ -- such, this will successfully parse all un-quoted Strings.+ parseUnqtList = quotedString parseList = oneOf [numString, stringBlock] `onFail`@@ -135,9 +155,9 @@ parse = parseList numString :: Parse String-numString = liftM show parseInt'+numString = liftM show parseStrictFloat `onFail`- liftM show parseFloat'+ liftM show parseInt' stringBlock :: Parse String stringBlock = do frst <- satisfy frstIDString@@ -149,9 +169,7 @@ quotedString = many stringInterior stringInterior :: Parse Char-stringInterior = stringRep quoteChar "\\\""- `onFail`- satisfy ((/=) quoteChar)+stringInterior = orQuote $ satisfy ((/=) quoteChar) parseSigned :: Real a => Parse a -> Parse a parseSigned p = (character '-' >> liftM negate p)@@ -170,25 +188,31 @@ parseInt' = parseSigned parseInt -- | Parse a floating point number that actually contains decimals.-parseStrictFloat :: (RealFrac a) => Parse a+parseStrictFloat :: Parse Double parseStrictFloat = parseSigned parseFloat parseFloat :: (RealFrac a) => Parse a parseFloat = do ds <- many (satisfy isDigit)- frac <- do character '.'- many (satisfy isDigit)- `adjustErrBad` (++ "\nexpected digit after .")- `adjustErr` (++ "expected decimal component")- expn <- parseExp `onFail` return 0- ( return . fromRational . (* (10^^(expn - length frac)))+ frac <- optional+ $ do character '.'+ many1 (satisfy isDigit)+ `adjustErr` (++ "\nexpected digit after .")+ when (isNothing frac && null ds)+ (fail "No actual digits in floating point number!")+ expn <- optional parseExp+ when (isNothing frac && isNothing expn)+ (fail "This is an integer, not a floating point number!")+ let frac' = fromMaybe "" frac+ expn' = fromMaybe 0 expn+ ( return . fromRational . (* (10^^(expn' - length frac'))) . (%1) . fst- . runParser parseInt) (ds++frac)+ . runParser parseInt) (ds++frac') `onFail` fail "Expected a floating point number" where parseExp = do character 'e'- commit ((character '+' >> parseInt)- `onFail`- parseSigned parseInt)+ ((character '+' >> parseInt)+ `onFail`+ parseInt') parseFloat' :: Parse Double parseFloat' = parseSigned ( parseFloat@@ -211,7 +235,7 @@ stringRep v = stringReps v . return stringReps :: a -> [String] -> Parse a-stringReps v ss = (oneOf $ map string ss) >> return v+stringReps v ss = oneOf (map string ss) >> return v strings :: [String] -> Parse String strings = oneOf . map string@@ -237,16 +261,21 @@ optionalQuotedString = optionalQuoted . string optionalQuoted :: Parse a -> Parse a-optionalQuoted p = p+optionalQuoted p = quotedParse p `onFail`- quotedParse p+ p -quotedParse :: Parse a -> Parse a-quotedParse p = bracket parseQuote parseQuote p+quotedParse :: Parse a -> Parse a+quotedParse = bracket parseQuote parseQuote parseQuote :: Parse Char parseQuote = character quoteChar +orQuote :: Parse Char -> Parse Char+orQuote p = stringRep quoteChar "\\\""+ `onFail`+ p+ quoteChar :: Char quoteChar = '"' @@ -318,8 +347,9 @@ -- | Remove unparseable features of Dot, such as comments and -- multi-line strings (which are converted to single-line strings).-preprocess :: String -> String-preprocess = fst . runParser parseOutUnwanted+preProcess :: String -> String+preProcess = fst . runParser parseOutUnwanted+ -- snd should be null -- | Parse out comments and make quoted strings spread over multiple -- lines only over a single line. Should parse the /entire/ input@@ -328,9 +358,9 @@ parseOutUnwanted = liftM concat (many getNext) where getNext :: Parse String- getNext = (oneOf [ parseLineComment, parseMultiLineComment ] >> return [])+ getNext = parseSplitStrings `onFail`- parseSplitStrings+ (oneOf [ parseLineComment, parseMultiLineComment ] >> return []) `onFail` liftM return next
Data/GraphViz/Types/Printing.hs view
@@ -10,7 +10,7 @@ combinators from that module. Note that the 'PrintDot' instances for 'Bool', etc. match those- specified for use with GraphViz.+ specified for use with Graphviz. You should only be using this module if you are writing custom node types for use with "Data.GraphViz.Types". For actual printing of@@ -24,7 +24,7 @@ * a number [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? ); - * any double-quoted string (\"...\") possibly containing escaped quotes (\");+ * any double-quoted string (\"...\") possibly containing escaped quotes (\\\"); * an HTML string (<...>). @@ -38,8 +38,10 @@ module Data.GraphViz.Types.Printing ( module Text.PrettyPrint , DotCode- , renderDot+ , renderDot -- Exported for Data.GraphViz.Types.printSGID , PrintDot(..)+ , printIt+ , addQuotes , wrap , commaDel , printField@@ -56,20 +58,23 @@ , renderStyle , fullRender )+ import qualified Text.PrettyPrint as PP +import Data.Word(Word8)+ -- ----------------------------------------------------------------------------- -- | A type alias to indicate what is being produced. type DotCode = Doc --- | Correctly render GraphViz output.+-- | Correctly render Graphviz output. renderDot :: DotCode -> String renderDot = PP.renderStyle style' where- style' = PP.style { PP.mode = PP.ZigZagMode }+ style' = PP.style { PP.mode = PP.LeftMode } --- | A class used to correctly print parts of the GraphViz Dot language.+-- | A class used to correctly print parts of the Graphviz Dot language. -- Minimal implementation is 'unqtDot'. class PrintDot a where -- | The unquoted representation, for use when composing values to@@ -96,12 +101,20 @@ listToDot :: [a] -> DotCode listToDot = doubleQuotes . unqtListToDot +-- | Convert to DotCode; note that this has no indentation, as we can+-- only have one of indentation and (possibly) infinite line lengths.+printIt :: (PrintDot a) => a -> String+printIt = renderDot . toDot+ instance PrintDot Int where unqtDot = int +instance PrintDot Word8 where+ unqtDot = int . fromIntegral+ instance PrintDot Double where -- If it's an "integral" double, then print as an integer.- -- This seems to match how GraphViz apps use Dot.+ -- This seems to match how Graphviz apps use Dot. unqtDot d = if d == fromIntegral di then int di else double d@@ -127,21 +140,25 @@ | restIDString c = char c -- Could be a number as well. | otherwise = doubleQuotes $ char c +needsQuotes :: String -> Bool+needsQuotes str+ | null str = True+ | isKeyword str = True+ | isIDString str = False+ | isNumString str = False+ | otherwise = True++addQuotes :: String -> DotCode -> DotCode+addQuotes = bool id doubleQuotes . needsQuotes+ -- | Escape quotes in Strings that need them.-unqtString :: String -> DotCode-unqtString str- | isIDString str = text str- | isNumString str = text str- | otherwise = text $ escapeQuotes str+unqtString :: String -> DotCode+unqtString "" = empty+unqtString str = text $ escapeQuotes str -- no quotes? no worries! -- | Escape quotes and quote Strings that need them (including keywords).-qtString :: String -> DotCode-qtString str- | isKeyword str = doubleQuotes $ text str- | isIDString str = text str- | isNumString str = text str- -- Don't use unqtString as it re-runs isIDString- | otherwise = doubleQuotes . text $ escapeQuotes str+qtString :: String -> DotCode+qtString str = addQuotes str $ unqtString str instance (PrintDot a) => PrintDot [a] where unqtDot = unqtListToDot
LICENSE view
@@ -1,5 +1,9 @@-Copyright (c) 2008, Matthew Sackman (matthew@wellquite.org)+The overall graphviz library is covered by this 3-Clause BSD license.+------------------------------------------------------------------- +Copyright (c) 2008-2009, Matthew Sackman+ Ivan Lazar Miljenovic+ All rights reserved. Redistribution and use in source and binary forms, with or without@@ -29,3 +33,55 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++================================================================================++The ColorBrewer Color Schemes (see Data.GraphViz.Attributes.Colors)+are covered by the following license:+-------------------------------------------------------------------+++Apache-Style Software License for ColorBrewer software and ColorBrewer+Color Schemes, Version 1.1++Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania+State University. All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ 1. Redistributions as source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ 2. The end-user documentation included with the redistribution, if+ any, must include the following acknowledgment:++ This product includes color specifications and designs developed+ by Cynthia Brewer (http://colorbrewer.org/).++ Alternately, this acknowledgment may appear in the software+ itself, if and wherever such third-party acknowledgments+ normally appear.++ 3. The name "ColorBrewer" must not be used to endorse or promote+ products derived from this software without prior written+ permission. For written permission, please contact Cynthia+ Brewer at cbrewer@psu.edu.++ 4. Products derived from this software may not be called+ "ColorBrewer", nor may "ColorBrewer" appear in their name,+ without prior written permission of Cynthia Brewer.++THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL CYNTHIA BREWER, MARK HARROWER, OR THE+PENNSYLVANIA STATE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+DAMAGE.
+ README view
@@ -0,0 +1,76 @@+The graphviz library provides bindings for Haskell to the Dot language+used by the Graphviz [1] suite of tools for graph visualisation. The+latest version of this library is available from Hackage [2].++[1] http://graphviz.org/+[2] http://hackage.haskell.org/package/graphviz++Features of the graphviz library include:++* Almost complete coverage of all Graphviz attributes, etc. for+ graphs, sub-graphs, clusters, nodes and edges:+ http://graphviz.org/doc/info/attrs.html++* Thorough documentation on known problems with the library and how it+ differs from the actual Dot specification.++* Support for specifying clusters.++* The ability to use a custom node type.++* Functions for running a Graphviz layout tool with all specified+ output types.++* The ability to not only generate but also parse Dot code (note that+ currently this is limited to a rather strict ordering of+ statements).++* Functions to convert FGL graphs to Dot code - including support to+ group them into clusters - with a high degree of customisation by+ specifying which attributes to use.++* Round-trip support for passing an FGL graph through Graphviz to+ augment node and edge labels with positional information.++Please note that currently the convenience functions are only+available for FGL [3] graphs; this will be extended in future once a+method for dealing with generic graph types is developed.++[3] http://web.engr.oregonstate.edu/~erwig/fgl/haskell/++--------------------------------------------------------------------------------++Developing graphviz+-------------------++Following are some notes on what to keep in mind if you want to+contribute to the development of graphviz:++* When printing and parsing values, there are two options: with or+ without quotes. Some values (e.g. numbers) may optionally be quoted+ in Dot code; others (namely strings with spaces, etc.) _must_ be+ quoted.++* Whenever you are parsing a type of value where the Dot+ representation of one is the prefix of the Dot representation of+ another, be sure to parse the longer value first.++* Because there are so many attributes, the definition, instances for+ and functions using the overall Attribute type are all defined using+ the AttributeGenerator.hs script. This file is not an actual part+ of the library, but should be used if any top-level work is being+ done for Attributes.++* Any changes should pass the testsuite, which is built by enabling+ the "test" flag. There are three ways of testing:++ - Run the graphviz-testsuite program; this takes approximately 90+ minutes to run and covers various properties that should hold.++ - Import the "Data.GraphViz.Testing" module for manual testing.++ - If you did not build the library with the "test" flag enabled, you+ can extract Data.GraphViz.Testing and Data.GraphViz.Testing.* from+ the source tarball to be able to use them directly; they only use+ graphviz's public API.+
+ RunTests.hs view
@@ -0,0 +1,16 @@+{- |+ Module : RunTests+ Description : Run the graphviz test suite.+ Copyright : (c) Ivan Lazar Miljenovic+ License : 3-Clause BSD-style+ Maintainer : Ivan.Miljenovic@gmail.com++ This module exists solely to make a Main module to build and run+ the test suite.+-}+module Main where++import Data.GraphViz.Testing++main :: IO ()+main = runDefaultTests
TODO view
@@ -2,8 +2,8 @@ * Utilise the generic graph class once it is finalised. -* Improve Output support.--* Find and fix the handle closing bug with graphvizWithHandle.+* Add generic versions (that is, order isn't important) of+ Data.GraphViz.Types -* Improve support for named Colors.+* Encoding: Graphviz uses UTF-8 by default, Latin1 when set; should+ graphviz use utf8-string and disable changing the encoding?
graphviz.cabal view
@@ -1,16 +1,18 @@ Name: graphviz-Version: 2999.6.0.0+Version: 2999.7.0.0 Stability: Beta-Synopsis: GraphViz bindings for Haskell.-Description: Provides convenient functions to convert FGL- graphs into the Dot language used by the- GraphViz (<http://graphviz.org/>) suite of- programs with a large degree of customisation+Synopsis: Graphviz bindings for Haskell.+Description: This library provides bindings for the Dot language+ used by the Graphviz (<http://graphviz.org/>)+ suite of programs. Also provided are+ convenience functions to convert FGL graphs into+ Dot code 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.+ and round-trip usage of Graphviz to attach+ positional data to each node and edge in the+ graph. Category: Graphs, Graphics License: BSD3 License-File: LICENSE@@ -21,21 +23,28 @@ Cabal-Version: >= 1.6 Extra-Source-Files: TODO Changelog+ README+ Data/GraphViz/AttributeGenerator.hs Source-Repository head Type: darcs Location: http://code.haskell.org/graphviz +Flag test+ Description: Build the test suite, including an executable to run it.+ Default: False+ Library { Build-Depends: base >= 3 && < 5, extensible-exceptions, containers, process,- array, fgl,- parallel >= 1.1 && < 1.2,+ filepath, polyparse >= 1.1,- pretty+ pretty,+ bytestring < 0.10,+ colour >= 2.3 && < 2.4 Exposed-Modules: Data.GraphViz Data.GraphViz.Types@@ -43,10 +52,31 @@ Data.GraphViz.Types.Printing Data.GraphViz.Commands Data.GraphViz.Attributes+ Data.GraphViz.Attributes.Colors Other-Modules: Data.GraphViz.Types.Clustering Data.GraphViz.Types.Internal+ if flag(test)+ Build-Depends: QuickCheck >= 2.1 && < 2.2 + Exposed-Modules: Data.GraphViz.Testing+ Data.GraphViz.Testing.Properties++ Other-Modules: Data.GraphViz.Testing.Instances+ Data.GraphViz.Testing.Instances.FGL+ Ghc-Options: -Wall Ghc-Prof-Options: -prof -auto-all+}++Executable graphviz-testsuite {++ if flag(test)+ Buildable: True+ else+ Buildable: False++ Main-Is: RunTests.hs++ GHC-Options: -O2 }