module Data.GraphViz.Attributes.Values where
import qualified Data.GraphViz.Attributes.HTML as Html
import Data.GraphViz.Attributes.Internal
import Data.GraphViz.Internal.State (getLayerListSep,
getLayerSep,
setLayerListSep,
setLayerSep)
import Data.GraphViz.Internal.Util (bool, stringToInt)
import Data.GraphViz.Parsing
import Data.GraphViz.Printing
import Data.List (intercalate)
import Data.Maybe (isJust)
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as T
import Data.Word (Word16)
import System.FilePath (searchPathSeparator, splitSearchPath)
type EscString = Text
data Rect = Rect Point Point
deriving (Eq, Ord, Show, Read)
instance PrintDot Rect where
unqtDot (Rect p1 p2) = printPoint2DUnqt p1 <> comma <> printPoint2DUnqt p2
toDot = dquotes . unqtDot
unqtListToDot = hsep . mapM unqtDot
instance ParseDot Rect where
parseUnqt = uncurry Rect <$> commaSep' parsePoint2D parsePoint2D
parse = quotedParse parseUnqt
parseUnqtList = sepBy1 parseUnqt whitespace1
data ClusterMode = Local
| Global
| NoCluster
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot ClusterMode where
unqtDot Local = text "local"
unqtDot Global = text "global"
unqtDot NoCluster = text "none"
instance ParseDot ClusterMode where
parseUnqt = oneOf [ stringRep Local "local"
, stringRep Global "global"
, stringRep NoCluster "none"
]
data DirType = Forward
| Back
| Both
| NoDir
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot DirType where
unqtDot Forward = text "forward"
unqtDot Back = text "back"
unqtDot Both = text "both"
unqtDot NoDir = text "none"
instance ParseDot DirType where
parseUnqt = oneOf [ stringRep Forward "forward"
, stringRep Back "back"
, stringRep Both "both"
, stringRep NoDir "none"
]
data DEConstraints = EdgeConstraints
| NoConstraints
| HierConstraints
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot DEConstraints where
unqtDot EdgeConstraints = unqtDot True
unqtDot NoConstraints = unqtDot False
unqtDot HierConstraints = text "hier"
instance ParseDot DEConstraints where
parseUnqt = fmap (bool NoConstraints EdgeConstraints) parse
`onFail`
stringRep HierConstraints "hier"
data DPoint = DVal Double
| PVal Point
deriving (Eq, Ord, Show, Read)
instance PrintDot DPoint where
unqtDot (DVal d) = unqtDot d
unqtDot (PVal p) = printPoint2DUnqt p
toDot (DVal d) = toDot d
toDot (PVal p) = printPoint2D p
instance ParseDot DPoint where
parseUnqt = optional (character '+')
*> oneOf [ PVal <$> parsePoint2D
, DVal <$> parseUnqt
]
parse = quotedParse parseUnqt
`onFail`
fmap DVal (parseSignedFloat False)
data SVGFontNames = SvgNames
| PostScriptNames
| FontConfigNames
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot SVGFontNames where
unqtDot SvgNames = text "svg"
unqtDot PostScriptNames = text "ps"
unqtDot FontConfigNames = text "gd"
instance ParseDot SVGFontNames where
parseUnqt = oneOf [ stringRep SvgNames "svg"
, stringRep PostScriptNames "ps"
, stringRep FontConfigNames "gd"
]
parse = stringRep SvgNames "\"\""
`onFail`
optionalQuoted parseUnqt
data GraphSize = GSize { width :: Double
, height :: Maybe Double
, desiredSize :: Bool
}
deriving (Eq, Ord, Show, Read)
instance PrintDot GraphSize where
unqtDot (GSize w mh ds) = bool id (<> char '!') ds
. maybe id (\h -> (<> unqtDot h) . (<> comma)) mh
$ unqtDot w
toDot (GSize w Nothing False) = toDot w
toDot gs = dquotes $ unqtDot gs
instance ParseDot GraphSize where
parseUnqt = GSize <$> parseUnqt
<*> optional (parseComma *> whitespace *> parseUnqt)
<*> (isJust <$> optional (character '!'))
parse = quotedParse parseUnqt
`onFail`
fmap (\ w -> GSize w Nothing False) (parseSignedFloat False)
data ModeType = Major
| KK
| Hier
| IpSep
| SpringMode
| MaxEnt
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot ModeType where
unqtDot Major = text "major"
unqtDot KK = text "KK"
unqtDot Hier = text "hier"
unqtDot IpSep = text "ipsep"
unqtDot SpringMode = text "spring"
unqtDot MaxEnt = text "maxent"
instance ParseDot ModeType where
parseUnqt = oneOf [ stringRep Major "major"
, stringRep KK "KK"
, stringRep Hier "hier"
, stringRep IpSep "ipsep"
, stringRep SpringMode "spring"
, stringRep MaxEnt "maxent"
]
data Model = ShortPath
| SubSet
| Circuit
| MDS
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot Model where
unqtDot ShortPath = text "shortpath"
unqtDot SubSet = text "subset"
unqtDot Circuit = text "circuit"
unqtDot MDS = text "mds"
instance ParseDot Model where
parseUnqt = oneOf [ stringRep ShortPath "shortpath"
, stringRep SubSet "subset"
, stringRep Circuit "circuit"
, stringRep MDS "mds"
]
data Label = StrLabel EscString
| HtmlLabel Html.Label
| RecordLabel RecordFields
deriving (Eq, Ord, Show, Read)
instance PrintDot Label where
unqtDot (StrLabel s) = unqtDot s
unqtDot (HtmlLabel h) = angled $ unqtDot h
unqtDot (RecordLabel fs) = unqtDot fs
toDot (StrLabel s) = toDot s
toDot h@HtmlLabel{} = unqtDot h
toDot (RecordLabel fs) = toDot fs
instance ParseDot Label where
parseUnqt = oneOf [ HtmlLabel <$> parseAngled parseUnqt
, RecordLabel <$> parseUnqt
, StrLabel <$> parseUnqt
]
parse = oneOf [ HtmlLabel <$> parseAngled parse
, RecordLabel <$> parse
, StrLabel <$> parse
]
type RecordFields = [RecordField]
data RecordField = LabelledTarget PortName EscString
| PortName PortName
| FieldLabel EscString
| FlipFields RecordFields
deriving (Eq, Ord, Show, Read)
instance PrintDot RecordField where
unqtDot (LabelledTarget t s) = printPortName t <+> unqtRecordString s
unqtDot (PortName t) = printPortName t
unqtDot (FieldLabel s) = unqtRecordString s
unqtDot (FlipFields rs) = braces $ unqtDot rs
toDot (FieldLabel s) = printEscaped recordEscChars s
toDot rf = dquotes $ unqtDot rf
unqtListToDot [f] = unqtDot f
unqtListToDot fs = hcat . punctuate (char '|') $ mapM unqtDot fs
listToDot [f] = toDot f
listToDot fs = dquotes $ unqtListToDot fs
instance ParseDot RecordField where
parseUnqt = (liftA2 maybe PortName LabelledTarget
<$> (PN <$> parseAngled parseRecord)
<*> optional (whitespace1 *> parseRecord)
)
`onFail`
fmap FieldLabel parseRecord
`onFail`
fmap FlipFields (parseBraced parseUnqt)
`onFail`
fail "Unable to parse RecordField"
parse = quotedParse parseUnqt
parseUnqtList = wrapWhitespace $ sepBy1 parseUnqt (wrapWhitespace $ character '|')
parseList = do rfs <- quotedParse parseUnqtList
if validRFs rfs
then return rfs
else fail "This is a StrLabel, not a RecordLabel"
where
validRFs [FieldLabel str] = T.any (`elem` recordEscChars) str
validRFs _ = True
printPortName :: PortName -> DotCode
printPortName = angled . unqtRecordString . portName
parseRecord :: Parse Text
parseRecord = parseEscaped False recordEscChars []
unqtRecordString :: Text -> DotCode
unqtRecordString = unqtEscaped recordEscChars
recordEscChars :: [Char]
recordEscChars = ['{', '}', '|', ' ', '<', '>']
data LabelScheme = NotEdgeLabel
| CloseToCenter
| CloseToOldCenter
| RemoveAndStraighten
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot LabelScheme where
unqtDot NotEdgeLabel = int 0
unqtDot CloseToCenter = int 1
unqtDot CloseToOldCenter = int 2
unqtDot RemoveAndStraighten = int 3
instance ParseDot LabelScheme where
parseUnqt = stringValue [ ("0", NotEdgeLabel)
, ("1", CloseToCenter)
, ("2", CloseToOldCenter)
, ("3", RemoveAndStraighten)
]
data Point = Point { xCoord :: Double
, yCoord :: Double
, zCoord :: Maybe Double
, forcePos :: Bool
}
deriving (Eq, Ord, Show, Read)
createPoint :: Double -> Double -> Point
createPoint x y = Point x y Nothing False
printPoint2DUnqt :: Point -> DotCode
printPoint2DUnqt p = commaDel (xCoord p) (yCoord p)
printPoint2D :: Point -> DotCode
printPoint2D = dquotes . printPoint2DUnqt
parsePoint2D :: Parse Point
parsePoint2D = uncurry createPoint <$> commaSepUnqt
instance PrintDot Point where
unqtDot (Point x y mz frs) = bool id (<> char '!') frs
. maybe id (\ z -> (<> unqtDot z) . (<> comma)) mz
$ commaDel x y
toDot = dquotes . unqtDot
unqtListToDot = hsep . mapM unqtDot
listToDot = dquotes . unqtListToDot
instance ParseDot Point where
parseUnqt = uncurry Point
<$> commaSepUnqt
<*> optional (parseComma *> parseUnqt)
<*> (isJust <$> optional (character '!'))
parse = quotedParse parseUnqt
parseUnqtList = sepBy1 parseUnqt whitespace1
data Overlap = KeepOverlaps
| ScaleOverlaps
| ScaleXYOverlaps
| PrismOverlap (Maybe Word16)
| VoronoiOverlap
| CompressOverlap
| VpscOverlap
| IpsepOverlap
deriving (Eq, Ord, Show, Read)
instance PrintDot Overlap where
unqtDot KeepOverlaps = unqtDot True
unqtDot ScaleOverlaps = text "scale"
unqtDot ScaleXYOverlaps = text "scalexy"
unqtDot (PrismOverlap i) = maybe id (flip (<>) . unqtDot) i $ text "prism"
unqtDot VoronoiOverlap = text "voronoi"
unqtDot CompressOverlap = text "compress"
unqtDot VpscOverlap = text "vpsc"
unqtDot IpsepOverlap = text "ipsep"
instance ParseDot Overlap where
parseUnqt = oneOf [ stringRep KeepOverlaps "true"
, stringRep ScaleXYOverlaps "scalexy"
, stringRep ScaleOverlaps "scale"
, string "prism" *> fmap PrismOverlap (optional parse)
, stringRep (PrismOverlap Nothing) "false"
, stringRep VoronoiOverlap "voronoi"
, stringRep CompressOverlap "compress"
, stringRep VpscOverlap "vpsc"
, stringRep IpsepOverlap "ipsep"
]
newtype LayerSep = LSep Text
deriving (Eq, Ord, Show, Read)
instance PrintDot LayerSep where
unqtDot (LSep ls) = setLayerSep (T.unpack ls) *> unqtDot ls
toDot (LSep ls) = setLayerSep (T.unpack ls) *> toDot ls
instance ParseDot LayerSep where
parseUnqt = do ls <- parseUnqt
setLayerSep $ T.unpack ls
return $ LSep ls
parse = do ls <- parse
setLayerSep $ T.unpack ls
return $ LSep ls
newtype LayerListSep = LLSep Text
deriving (Eq, Ord, Show, Read)
instance PrintDot LayerListSep where
unqtDot (LLSep ls) = setLayerListSep (T.unpack ls) *> unqtDot ls
toDot (LLSep ls) = setLayerListSep (T.unpack ls) *> toDot ls
instance ParseDot LayerListSep where
parseUnqt = do ls <- parseUnqt
setLayerListSep $ T.unpack ls
return $ LLSep ls
parse = do ls <- parse
setLayerListSep $ T.unpack ls
return $ LLSep ls
type LayerRange = [LayerRangeElem]
data LayerRangeElem = LRID LayerID
| LRS LayerID LayerID
deriving (Eq, Ord, Show, Read)
instance PrintDot LayerRangeElem where
unqtDot (LRID lid) = unqtDot lid
unqtDot (LRS id1 id2) = do ls <- getLayerSep
let s = unqtDot $ head ls
unqtDot id1 <> s <> unqtDot id2
toDot (LRID lid) = toDot lid
toDot lrs = dquotes $ unqtDot lrs
unqtListToDot lr = do lls <- getLayerListSep
let s = unqtDot $ head lls
hcat . punctuate s $ mapM unqtDot lr
listToDot [lre] = toDot lre
listToDot lrs = dquotes $ unqtListToDot lrs
instance ParseDot LayerRangeElem where
parseUnqt = ignoreSep LRS parseUnqt parseLayerSep parseUnqt
`onFail`
fmap LRID parseUnqt
parse = quotedParse (ignoreSep LRS parseUnqt parseLayerSep parseUnqt)
`onFail`
fmap LRID parse
parseUnqtList = sepBy parseUnqt parseLayerListSep
parseList = quotedParse parseUnqtList
`onFail`
fmap ((:[]) . LRID) parse
parseLayerSep :: Parse ()
parseLayerSep = do ls <- getLayerSep
many1Satisfy (`elem` ls) *> return ()
parseLayerName :: Parse Text
parseLayerName = parseEscaped False [] =<< liftA2 (++) getLayerSep getLayerListSep
parseLayerName' :: Parse Text
parseLayerName' = stringBlock
`onFail`
quotedParse parseLayerName
parseLayerListSep :: Parse ()
parseLayerListSep = do lls <- getLayerListSep
many1Satisfy (`elem` lls) *> return ()
data LayerID = AllLayers
| LRInt Int
| LRName Text
deriving (Eq, Ord, Show, Read)
instance PrintDot LayerID where
unqtDot AllLayers = text "all"
unqtDot (LRInt n) = unqtDot n
unqtDot (LRName nm) = unqtDot nm
toDot (LRName nm) = toDot nm
toDot li = unqtDot li
unqtListToDot ll = do ls <- getLayerSep
let s = unqtDot $ head ls
hcat . punctuate s $ mapM unqtDot ll
listToDot [l] = toDot l
listToDot ll = dquotes $ unqtDot ll
instance ParseDot LayerID where
parseUnqt = checkLayerName <$> parseLayerName
parse = oneOf [ checkLayerName <$> parseLayerName'
, LRInt <$> parse
]
checkLayerName :: Text -> LayerID
checkLayerName str = maybe checkAll LRInt $ stringToInt str
where
checkAll = if T.toLower str == "all"
then AllLayers
else LRName str
newtype LayerList = LL [LayerID]
deriving (Eq, Ord, Show, Read)
instance PrintDot LayerList where
unqtDot (LL ll) = unqtDot ll
toDot (LL ll) = toDot ll
instance ParseDot LayerList where
parseUnqt = LL <$> sepBy1 parseUnqt parseLayerSep
parse = quotedParse parseUnqt
`onFail`
fmap (LL . (:[]) . LRName) stringBlock
`onFail`
quotedParse (stringRep (LL []) "")
data Order = OutEdges
| InEdges
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot Order where
unqtDot OutEdges = text "out"
unqtDot InEdges = text "in"
instance ParseDot Order where
parseUnqt = oneOf [ stringRep OutEdges "out"
, stringRep InEdges "in"
]
data OutputMode = BreadthFirst | NodesFirst | EdgesFirst
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot OutputMode where
unqtDot BreadthFirst = text "breadthfirst"
unqtDot NodesFirst = text "nodesfirst"
unqtDot EdgesFirst = text "edgesfirst"
instance ParseDot OutputMode where
parseUnqt = oneOf [ stringRep BreadthFirst "breadthfirst"
, stringRep NodesFirst "nodesfirst"
, stringRep EdgesFirst "edgesfirst"
]
data Pack = DoPack
| DontPack
| PackMargin Int
deriving (Eq, Ord, Show, Read)
instance PrintDot Pack where
unqtDot DoPack = unqtDot True
unqtDot DontPack = unqtDot False
unqtDot (PackMargin m) = unqtDot m
instance ParseDot Pack where
parseUnqt = oneOf [ PackMargin <$> parseUnqt
, bool DontPack DoPack <$> onlyBool
]
data PackMode = PackNode
| PackClust
| PackGraph
| PackArray Bool Bool (Maybe Int)
deriving (Eq, Ord, Show, Read)
instance PrintDot PackMode where
unqtDot PackNode = text "node"
unqtDot PackClust = text "clust"
unqtDot PackGraph = text "graph"
unqtDot (PackArray c u mi) = addNum . isU . isC . isUnder
$ text "array"
where
addNum = maybe id (flip (<>) . unqtDot) mi
isUnder = if c || u
then (<> char '_')
else id
isC = if c
then (<> char 'c')
else id
isU = if u
then (<> char 'u')
else id
instance ParseDot PackMode where
parseUnqt = oneOf [ stringRep PackNode "node"
, stringRep PackClust "clust"
, stringRep PackGraph "graph"
, do string "array"
mcu <- optional $ character '_' *> many1 (satisfy isCU)
let c = hasCharacter mcu 'c'
u = hasCharacter mcu 'u'
mi <- optional parseUnqt
return $ PackArray c u mi
]
where
hasCharacter ms c = maybe False (elem c) ms
isCU = (`elem` ['c', 'u'])
data Pos = PointPos Point
| SplinePos [Spline]
deriving (Eq, Ord, Show, Read)
instance PrintDot Pos where
unqtDot (PointPos p) = unqtDot p
unqtDot (SplinePos ss) = unqtDot ss
toDot (PointPos p) = toDot p
toDot (SplinePos ss) = toDot ss
instance ParseDot Pos where
parseUnqt = do splns <- parseUnqt
case splns of
[Spline Nothing Nothing [p]] -> return $ PointPos p
_ -> return $ SplinePos splns
parse = quotedParse parseUnqt
data EdgeType = SplineEdges
| LineEdges
| NoEdges
| PolyLine
| Ortho
| Curved
| CompoundEdge
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot EdgeType where
unqtDot SplineEdges = text "spline"
unqtDot LineEdges = text "line"
unqtDot NoEdges = empty
unqtDot PolyLine = text "polyline"
unqtDot Ortho = text "ortho"
unqtDot Curved = text "curved"
unqtDot CompoundEdge = text "compound"
toDot NoEdges = dquotes empty
toDot et = unqtDot et
instance ParseDot EdgeType where
parseUnqt = oneOf [ bool LineEdges SplineEdges <$> parse
, stringRep SplineEdges "spline"
, stringRep LineEdges "line"
, stringRep NoEdges "none"
, stringRep PolyLine "polyline"
, stringRep Ortho "ortho"
, stringRep Curved "curved"
, stringRep CompoundEdge "compound"
]
parse = stringRep NoEdges "\"\""
`onFail`
optionalQuoted parseUnqt
data PageDir = Bl | Br | Tl | Tr | Rb | Rt | Lb | Lt
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot PageDir where
unqtDot Bl = text "BL"
unqtDot Br = text "BR"
unqtDot Tl = text "TL"
unqtDot Tr = text "TR"
unqtDot Rb = text "RB"
unqtDot Rt = text "RT"
unqtDot Lb = text "LB"
unqtDot Lt = text "LT"
instance ParseDot PageDir where
parseUnqt = stringValue [ ("BL", Bl)
, ("BR", Br)
, ("TL", Tl)
, ("TR", Tr)
, ("RB", Rb)
, ("RT", Rt)
, ("LB", Lb)
, ("LT", Lt)
]
data Spline = Spline { endPoint :: Maybe Point
, startPoint :: Maybe Point
, splinePoints :: [Point]
}
deriving (Eq, Ord, Show, Read)
instance PrintDot Spline where
unqtDot (Spline me ms ps) = addE . addS
. hsep
$ mapM unqtDot ps
where
addP t = maybe id ((<+>) . commaDel t)
addS = addP 's' ms
addE = addP 'e' me
toDot = dquotes . unqtDot
unqtListToDot = hcat . punctuate semi . mapM unqtDot
listToDot = dquotes . unqtListToDot
instance ParseDot Spline where
parseUnqt = Spline <$> parseP 'e' <*> parseP 's'
<*> sepBy1 parseUnqt whitespace1
where
parseP t = optional (character t *> parseComma *> parseUnqt <* whitespace1)
parse = quotedParse parseUnqt
parseUnqtList = sepBy1 parseUnqt (character ';')
data QuadType = NormalQT
| FastQT
| NoQT
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot QuadType where
unqtDot NormalQT = text "normal"
unqtDot FastQT = text "fast"
unqtDot NoQT = text "none"
instance ParseDot QuadType where
parseUnqt = oneOf [ stringRep NormalQT "normal"
, stringRep FastQT "fast"
, stringRep NoQT "none"
, character '2' *> return FastQT
, bool NoQT NormalQT <$> parse
]
data Root = IsCentral
| NotCentral
| NodeName Text
deriving (Eq, Ord, Show, Read)
instance PrintDot Root where
unqtDot IsCentral = unqtDot True
unqtDot NotCentral = unqtDot False
unqtDot (NodeName n) = unqtDot n
toDot (NodeName n) = toDot n
toDot r = unqtDot r
instance ParseDot Root where
parseUnqt = fmap (bool NotCentral IsCentral) onlyBool
`onFail`
fmap NodeName parseUnqt
parse = optionalQuoted (bool NotCentral IsCentral <$> onlyBool)
`onFail`
fmap NodeName parse
data RankType = SameRank
| MinRank
| SourceRank
| MaxRank
| SinkRank
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot RankType where
unqtDot SameRank = text "same"
unqtDot MinRank = text "min"
unqtDot SourceRank = text "source"
unqtDot MaxRank = text "max"
unqtDot SinkRank = text "sink"
instance ParseDot RankType where
parseUnqt = stringValue [ ("same", SameRank)
, ("min", MinRank)
, ("source", SourceRank)
, ("max", MaxRank)
, ("sink", SinkRank)
]
data RankDir = FromTop
| FromLeft
| FromBottom
| FromRight
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot RankDir where
unqtDot FromTop = text "TB"
unqtDot FromLeft = text "LR"
unqtDot FromBottom = text "BT"
unqtDot FromRight = text "RL"
instance ParseDot RankDir where
parseUnqt = oneOf [ stringRep FromTop "TB"
, stringRep FromLeft "LR"
, stringRep FromBottom "BT"
, stringRep FromRight "RL"
]
data Shape
= BoxShape
| Polygon
| Ellipse
| Circle
| PointShape
| Egg
| Triangle
| PlainText
| DiamondShape
| Trapezium
| Parallelogram
| House
| Pentagon
| Hexagon
| Septagon
| Octagon
| DoubleCircle
| DoubleOctagon
| TripleOctagon
| InvTriangle
| InvTrapezium
| InvHouse
| MDiamond
| MSquare
| MCircle
| Square
| Star
| Underline
| Note
| Tab
| Folder
| Box3D
| Component
| Promoter
| CDS
| Terminator
| UTR
| PrimerSite
| RestrictionSite
| FivePovOverhang
| ThreePovOverhang
| NoOverhang
| Assembly
| Signature
| Insulator
| Ribosite
| RNAStab
| ProteaseSite
| ProteinStab
| RPromoter
| RArrow
| LArrow
| LPromoter
| Record
| MRecord
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot Shape where
unqtDot BoxShape = text "box"
unqtDot Polygon = text "polygon"
unqtDot Ellipse = text "ellipse"
unqtDot Circle = text "circle"
unqtDot PointShape = text "point"
unqtDot Egg = text "egg"
unqtDot Triangle = text "triangle"
unqtDot PlainText = text "plaintext"
unqtDot DiamondShape = text "diamond"
unqtDot Trapezium = text "trapezium"
unqtDot Parallelogram = text "parallelogram"
unqtDot House = text "house"
unqtDot Pentagon = text "pentagon"
unqtDot Hexagon = text "hexagon"
unqtDot Septagon = text "septagon"
unqtDot Octagon = text "octagon"
unqtDot DoubleCircle = text "doublecircle"
unqtDot DoubleOctagon = text "doubleoctagon"
unqtDot TripleOctagon = text "tripleoctagon"
unqtDot InvTriangle = text "invtriangle"
unqtDot InvTrapezium = text "invtrapezium"
unqtDot InvHouse = text "invhouse"
unqtDot MDiamond = text "Mdiamond"
unqtDot MSquare = text "Msquare"
unqtDot MCircle = text "Mcircle"
unqtDot Square = text "square"
unqtDot Star = text "star"
unqtDot Underline = text "underline"
unqtDot Note = text "note"
unqtDot Tab = text "tab"
unqtDot Folder = text "folder"
unqtDot Box3D = text "box3d"
unqtDot Component = text "component"
unqtDot Promoter = text "promoter"
unqtDot CDS = text "cds"
unqtDot Terminator = text "terminator"
unqtDot UTR = text "utr"
unqtDot PrimerSite = text "primersite"
unqtDot RestrictionSite = text "restrictionsite"
unqtDot FivePovOverhang = text "fivepovoverhang"
unqtDot ThreePovOverhang = text "threepovoverhang"
unqtDot NoOverhang = text "nooverhang"
unqtDot Assembly = text "assembly"
unqtDot Signature = text "signature"
unqtDot Insulator = text "insulator"
unqtDot Ribosite = text "ribosite"
unqtDot RNAStab = text "rnastab"
unqtDot ProteaseSite = text "proteasesite"
unqtDot ProteinStab = text "proteinstab"
unqtDot RPromoter = text "rpromoter"
unqtDot RArrow = text "rarrow"
unqtDot LArrow = text "larrow"
unqtDot LPromoter = text "lpromoter"
unqtDot Record = text "record"
unqtDot MRecord = text "Mrecord"
instance ParseDot Shape where
parseUnqt = stringValue [ ("box3d", Box3D)
, ("box", BoxShape)
, ("rectangle", BoxShape)
, ("rect", BoxShape)
, ("polygon", Polygon)
, ("ellipse", Ellipse)
, ("oval", Ellipse)
, ("circle", Circle)
, ("point", PointShape)
, ("egg", Egg)
, ("triangle", Triangle)
, ("plaintext", PlainText)
, ("none", PlainText)
, ("diamond", DiamondShape)
, ("trapezium", Trapezium)
, ("parallelogram", Parallelogram)
, ("house", House)
, ("pentagon", Pentagon)
, ("hexagon", Hexagon)
, ("septagon", Septagon)
, ("octagon", Octagon)
, ("doublecircle", DoubleCircle)
, ("doubleoctagon", DoubleOctagon)
, ("tripleoctagon", TripleOctagon)
, ("invtriangle", InvTriangle)
, ("invtrapezium", InvTrapezium)
, ("invhouse", InvHouse)
, ("Mdiamond", MDiamond)
, ("Msquare", MSquare)
, ("Mcircle", MCircle)
, ("square", Square)
, ("star", Star)
, ("underline", Underline)
, ("note", Note)
, ("tab", Tab)
, ("folder", Folder)
, ("component", Component)
, ("promoter", Promoter)
, ("cds", CDS)
, ("terminator", Terminator)
, ("utr", UTR)
, ("primersite", PrimerSite)
, ("restrictionsite", RestrictionSite)
, ("fivepovoverhang", FivePovOverhang)
, ("threepovoverhang", ThreePovOverhang)
, ("nooverhang", NoOverhang)
, ("assembly", Assembly)
, ("signature", Signature)
, ("insulator", Insulator)
, ("ribosite", Ribosite)
, ("rnastab", RNAStab)
, ("proteasesite", ProteaseSite)
, ("proteinstab", ProteinStab)
, ("rpromoter", RPromoter)
, ("rarrow", RArrow)
, ("larrow", LArrow)
, ("lpromoter", LPromoter)
, ("record", Record)
, ("Mrecord", MRecord)
]
data SmoothType = NoSmooth
| AvgDist
| GraphDist
| PowerDist
| RNG
| Spring
| TriangleSmooth
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot SmoothType where
unqtDot NoSmooth = text "none"
unqtDot AvgDist = text "avg_dist"
unqtDot GraphDist = text "graph_dist"
unqtDot PowerDist = text "power_dist"
unqtDot RNG = text "rng"
unqtDot Spring = text "spring"
unqtDot TriangleSmooth = text "triangle"
instance ParseDot SmoothType where
parseUnqt = oneOf [ stringRep NoSmooth "none"
, stringRep AvgDist "avg_dist"
, stringRep GraphDist "graph_dist"
, stringRep PowerDist "power_dist"
, stringRep RNG "rng"
, stringRep Spring "spring"
, stringRep TriangleSmooth "triangle"
]
data StartType = StartStyle STStyle
| StartSeed Int
| StartStyleSeed STStyle Int
deriving (Eq, Ord, Show, Read)
instance PrintDot StartType where
unqtDot (StartStyle ss) = unqtDot ss
unqtDot (StartSeed s) = unqtDot s
unqtDot (StartStyleSeed ss s) = unqtDot ss <> unqtDot s
instance ParseDot StartType where
parseUnqt = oneOf [ liftA2 StartStyleSeed parseUnqt parseUnqt
, StartStyle <$> parseUnqt
, StartSeed <$> parseUnqt
]
data STStyle = RegularStyle
| SelfStyle
| RandomStyle
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot STStyle where
unqtDot RegularStyle = text "regular"
unqtDot SelfStyle = text "self"
unqtDot RandomStyle = text "random"
instance ParseDot STStyle where
parseUnqt = oneOf [ stringRep RegularStyle "regular"
, stringRep SelfStyle "self"
, stringRep RandomStyle "random"
]
data StyleItem = SItem StyleName [Text]
deriving (Eq, Ord, Show, Read)
instance PrintDot StyleItem where
unqtDot (SItem nm args)
| null args = dnm
| otherwise = dnm <> parens args'
where
dnm = unqtDot nm
args' = hcat . punctuate comma $ mapM unqtDot args
toDot si@(SItem nm args)
| null args = toDot nm
| otherwise = dquotes $ unqtDot si
unqtListToDot = hcat . punctuate comma . mapM unqtDot
listToDot [SItem nm []] = toDot nm
listToDot sis = dquotes $ unqtListToDot sis
instance ParseDot StyleItem where
parseUnqt = liftA2 SItem parseUnqt (tryParseList' parseArgs)
parse = quotedParse (liftA2 SItem parseUnqt parseArgs)
`onFail`
fmap (`SItem` []) parse
parseUnqtList = sepBy1 parseUnqt parseComma
parseList = quotedParse parseUnqtList
`onFail`
fmap return parse
parseArgs :: Parse [Text]
parseArgs = bracketSep (character '(')
parseComma
(character ')')
parseStyleName
data StyleName = Dashed
| Dotted
| Solid
| Bold
| Invisible
| Filled
| Striped
| Wedged
| Diagonals
| Rounded
| Tapered
| Radial
| DD Text
deriving (Eq, Ord, Show, Read)
instance PrintDot StyleName where
unqtDot Dashed = text "dashed"
unqtDot Dotted = text "dotted"
unqtDot Solid = text "solid"
unqtDot Bold = text "bold"
unqtDot Invisible = text "invis"
unqtDot Filled = text "filled"
unqtDot Striped = text "striped"
unqtDot Wedged = text "wedged"
unqtDot Diagonals = text "diagonals"
unqtDot Rounded = text "rounded"
unqtDot Tapered = text "tapered"
unqtDot Radial = text "radial"
unqtDot (DD nm) = unqtDot nm
toDot (DD nm) = toDot nm
toDot sn = unqtDot sn
instance ParseDot StyleName where
parseUnqt = checkDD <$> parseStyleName
parse = quotedParse parseUnqt
`onFail`
fmap checkDD quotelessString
checkDD :: Text -> StyleName
checkDD str = case T.toLower str of
"dashed" -> Dashed
"dotted" -> Dotted
"solid" -> Solid
"bold" -> Bold
"invis" -> Invisible
"filled" -> Filled
"striped" -> Striped
"wedged" -> Wedged
"diagonals" -> Diagonals
"rounded" -> Rounded
"tapered" -> Tapered
"radial" -> Radial
_ -> DD str
parseStyleName :: Parse Text
parseStyleName = liftA2 T.cons (orEscaped . noneOf $ ' ' : disallowedChars)
(parseEscaped True [] disallowedChars)
where
disallowedChars = [quoteChar, '(', ')', ',']
orSlash p = stringRep '\\' "\\\\" `onFail` p
orEscaped = orQuote . orSlash
data ViewPort = VP { wVal :: Double
, hVal :: Double
, zVal :: Double
, focus :: Maybe FocusType
}
deriving (Eq, Ord, Show, Read)
instance PrintDot ViewPort where
unqtDot vp = maybe vs ((<>) (vs <> comma) . unqtDot)
$ focus vp
where
vs = hcat . punctuate comma
$ mapM (unqtDot . ($vp)) [wVal, hVal, zVal]
toDot = dquotes . unqtDot
instance ParseDot ViewPort where
parseUnqt = VP <$> parseUnqt
<* parseComma
<*> parseUnqt
<* parseComma
<*> parseUnqt
<*> optional (parseComma *> parseUnqt)
parse = quotedParse parseUnqt
data FocusType = XY Point
| NodeFocus Text
deriving (Eq, Ord, Show, Read)
instance PrintDot FocusType where
unqtDot (XY p) = unqtDot p
unqtDot (NodeFocus nm) = unqtDot nm
toDot (XY p) = toDot p
toDot (NodeFocus nm) = toDot nm
instance ParseDot FocusType where
parseUnqt = fmap XY parseUnqt
`onFail`
fmap NodeFocus parseUnqt
parse = fmap XY parse
`onFail`
fmap NodeFocus parse
data VerticalPlacement = VTop
| VCenter
| VBottom
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot VerticalPlacement where
unqtDot VTop = char 't'
unqtDot VCenter = char 'c'
unqtDot VBottom = char 'b'
instance ParseDot VerticalPlacement where
parseUnqt = oneOf [ stringRep VTop "t"
, stringRep VCenter "c"
, stringRep VBottom "b"
]
newtype Paths = Paths { paths :: [FilePath] }
deriving (Eq, Ord, Show, Read)
instance PrintDot Paths where
unqtDot = unqtDot . intercalate [searchPathSeparator] . paths
toDot (Paths [p]) = toDot p
toDot ps = dquotes $ unqtDot ps
instance ParseDot Paths where
parseUnqt = Paths . splitSearchPath <$> parseUnqt
parse = quotedParse parseUnqt
`onFail`
fmap (Paths . (:[]) . T.unpack) quotelessString
data ScaleType = UniformScale
| NoScale
| FillWidth
| FillHeight
| FillBoth
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot ScaleType where
unqtDot UniformScale = unqtDot True
unqtDot NoScale = unqtDot False
unqtDot FillWidth = text "width"
unqtDot FillHeight = text "height"
unqtDot FillBoth = text "both"
instance ParseDot ScaleType where
parseUnqt = oneOf [ stringRep UniformScale "true"
, stringRep NoScale "false"
, stringRep FillWidth "width"
, stringRep FillHeight "height"
, stringRep FillBoth "both"
]
data Justification = JLeft
| JRight
| JCenter
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot Justification where
unqtDot JLeft = char 'l'
unqtDot JRight = char 'r'
unqtDot JCenter = char 'c'
instance ParseDot Justification where
parseUnqt = oneOf [ stringRep JLeft "l"
, stringRep JRight "r"
, stringRep JCenter "c"
]
data Ratios = AspectRatio Double
| FillRatio
| CompressRatio
| ExpandRatio
| AutoRatio
deriving (Eq, Ord, Show, Read)
instance PrintDot Ratios where
unqtDot (AspectRatio r) = unqtDot r
unqtDot FillRatio = text "fill"
unqtDot CompressRatio = text "compress"
unqtDot ExpandRatio = text "expand"
unqtDot AutoRatio = text "auto"
toDot (AspectRatio r) = toDot r
toDot r = unqtDot r
instance ParseDot Ratios where
parseUnqt = parseRatio True
parse = quotedParse parseUnqt <|> parseRatio False
parseRatio :: Bool -> Parse Ratios
parseRatio q = oneOf [ AspectRatio <$> parseSignedFloat q
, stringRep FillRatio "fill"
, stringRep CompressRatio "compress"
, stringRep ExpandRatio "expand"
, stringRep AutoRatio "auto"
]
data Number = Int Int
| Dbl Double
deriving (Eq, Ord, Show, Read)
instance PrintDot Number where
unqtDot (Int i) = unqtDot i
unqtDot (Dbl d) = unqtDot d
toDot (Int i) = toDot i
toDot (Dbl d) = toDot d
instance ParseDot Number where
parseUnqt = parseNumber True
parse = quotedParse parseUnqt
<|>
parseNumber False
parseNumber :: Bool -> Parse Number
parseNumber q = Dbl <$> parseStrictFloat q
<|>
Int <$> parseUnqt
data Normalized = IsNormalized
| NotNormalized
| NormalizedAngle Double
deriving (Eq, Ord, Show, Read)
instance PrintDot Normalized where
unqtDot IsNormalized = unqtDot True
unqtDot NotNormalized = unqtDot False
unqtDot (NormalizedAngle a) = unqtDot a
toDot (NormalizedAngle a) = toDot a
toDot norm = unqtDot norm
instance ParseDot Normalized where
parseUnqt = parseNormalized True
parse = quotedParse parseUnqt <|> parseNormalized False
parseNormalized :: Bool -> Parse Normalized
parseNormalized q = NormalizedAngle <$> parseSignedFloat q
<|>
bool NotNormalized IsNormalized <$> onlyBool
data NodeSize = GrowAsNeeded
| SetNodeSize
| SetShapeSize
deriving (Eq, Ord, Bounded, Enum, Show, Read)
instance PrintDot NodeSize where
unqtDot GrowAsNeeded = unqtDot False
unqtDot SetNodeSize = unqtDot True
unqtDot SetShapeSize = text "shape"
instance ParseDot NodeSize where
parseUnqt = bool GrowAsNeeded SetNodeSize <$> parseUnqt
<|>
stringRep SetShapeSize "shape"