graphviz 2999.14.1.0 → 2999.15.0.0
raw patch · 27 files changed
+2522/−2120 lines, 27 filesdep ~QuickCheckdep ~bytestringPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: QuickCheck, bytestring
API changes (from Hackage documentation)
- Data.GraphViz.Attributes: box, vee, tee, normal, noArrow, inv, dotArrow, diamond, crow :: Arrow
- Data.GraphViz.Attributes: oDot, oDiamond, oBox, invODot, invDot :: Arrow
+ Data.GraphViz: isDotCluster :: GraphvizParams n nl el cl l -> (cl -> Bool)
+ Data.GraphViz.Attributes: Assembly :: Shape
+ Data.GraphViz.Attributes: CDS :: Shape
+ Data.GraphViz.Attributes: FivePovOverhang :: Shape
+ Data.GraphViz.Attributes: Insulator :: Shape
+ Data.GraphViz.Attributes: LArrow :: Shape
+ Data.GraphViz.Attributes: LPromoter :: Shape
+ Data.GraphViz.Attributes: NoOverhang :: Shape
+ Data.GraphViz.Attributes: PrimerSite :: Shape
+ Data.GraphViz.Attributes: Promoter :: Shape
+ Data.GraphViz.Attributes: ProteaseSite :: Shape
+ Data.GraphViz.Attributes: ProteinStab :: Shape
+ Data.GraphViz.Attributes: RArrow :: Shape
+ Data.GraphViz.Attributes: RNAStab :: Shape
+ Data.GraphViz.Attributes: RPromoter :: Shape
+ Data.GraphViz.Attributes: RestrictionSite :: Shape
+ Data.GraphViz.Attributes: Ribosite :: Shape
+ Data.GraphViz.Attributes: Signature :: Shape
+ Data.GraphViz.Attributes: Terminator :: Shape
+ Data.GraphViz.Attributes: ThreePovOverhang :: Shape
+ Data.GraphViz.Attributes: UTR :: Shape
+ Data.GraphViz.Attributes: box :: Arrow
+ Data.GraphViz.Attributes: crow :: Arrow
+ Data.GraphViz.Attributes: diamond :: Arrow
+ Data.GraphViz.Attributes: dotArrow :: Arrow
+ Data.GraphViz.Attributes: inv :: Arrow
+ Data.GraphViz.Attributes: invDot :: Arrow
+ Data.GraphViz.Attributes: invODot :: Arrow
+ Data.GraphViz.Attributes: noArrow :: Arrow
+ Data.GraphViz.Attributes: normal :: Arrow
+ Data.GraphViz.Attributes: oBox :: Arrow
+ Data.GraphViz.Attributes: oDiamond :: Arrow
+ Data.GraphViz.Attributes: oDot :: Arrow
+ Data.GraphViz.Attributes: tee :: Arrow
+ Data.GraphViz.Attributes: vee :: Arrow
+ Data.GraphViz.Attributes.Complete: Assembly :: Shape
+ Data.GraphViz.Attributes.Complete: CDS :: Shape
+ Data.GraphViz.Attributes.Complete: FivePovOverhang :: Shape
+ Data.GraphViz.Attributes.Complete: FontConfigNames :: SVGFontNames
+ Data.GraphViz.Attributes.Complete: GSize :: Double -> Maybe Double -> Bool -> GraphSize
+ Data.GraphViz.Attributes.Complete: Insulator :: Shape
+ Data.GraphViz.Attributes.Complete: LArrow :: Shape
+ Data.GraphViz.Attributes.Complete: LPromoter :: Shape
+ Data.GraphViz.Attributes.Complete: NoOverhang :: Shape
+ Data.GraphViz.Attributes.Complete: PostScriptNames :: SVGFontNames
+ Data.GraphViz.Attributes.Complete: PrimerSite :: Shape
+ Data.GraphViz.Attributes.Complete: Promoter :: Shape
+ Data.GraphViz.Attributes.Complete: ProteaseSite :: Shape
+ Data.GraphViz.Attributes.Complete: ProteinStab :: Shape
+ Data.GraphViz.Attributes.Complete: RArrow :: Shape
+ Data.GraphViz.Attributes.Complete: RNAStab :: Shape
+ Data.GraphViz.Attributes.Complete: RPromoter :: Shape
+ Data.GraphViz.Attributes.Complete: RestrictionSite :: Shape
+ Data.GraphViz.Attributes.Complete: Ribosite :: Shape
+ Data.GraphViz.Attributes.Complete: Signature :: Shape
+ Data.GraphViz.Attributes.Complete: SvgNames :: SVGFontNames
+ Data.GraphViz.Attributes.Complete: Terminator :: Shape
+ Data.GraphViz.Attributes.Complete: ThreePovOverhang :: Shape
+ Data.GraphViz.Attributes.Complete: UTR :: Shape
+ Data.GraphViz.Attributes.Complete: data GraphSize
+ Data.GraphViz.Attributes.Complete: data SVGFontNames
+ Data.GraphViz.Attributes.Complete: desiredSize :: GraphSize -> Bool
+ Data.GraphViz.Attributes.Complete: endPoint :: Spline -> Maybe Point
+ Data.GraphViz.Attributes.Complete: height :: GraphSize -> Maybe Double
+ Data.GraphViz.Attributes.Complete: instance Bounded SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance Enum SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance Eq GraphSize
+ Data.GraphViz.Attributes.Complete: instance Eq SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance Ord GraphSize
+ Data.GraphViz.Attributes.Complete: instance Ord SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance ParseDot GraphSize
+ Data.GraphViz.Attributes.Complete: instance ParseDot SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance PrintDot GraphSize
+ Data.GraphViz.Attributes.Complete: instance PrintDot SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance Read GraphSize
+ Data.GraphViz.Attributes.Complete: instance Read SVGFontNames
+ Data.GraphViz.Attributes.Complete: instance Show GraphSize
+ Data.GraphViz.Attributes.Complete: instance Show SVGFontNames
+ Data.GraphViz.Attributes.Complete: splinePoints :: Spline -> [Point]
+ Data.GraphViz.Attributes.Complete: startPoint :: Spline -> Maybe Point
+ Data.GraphViz.Attributes.Complete: width :: GraphSize -> Double
+ Data.GraphViz.Parsing: ignoreSep :: (a -> b -> c) -> Parse a -> Parse sep -> Parse b -> Parse c
+ Data.GraphViz.Parsing: liftEqParse :: Parse a -> String -> (a -> b) -> Parse b
+ Data.GraphViz.Parsing: liftEqParse' :: ParseDot a => String -> (a -> b) -> Parse b
+ Data.GraphViz.Parsing: parseFieldNumDef :: ParseDot a => (a -> b) -> a -> String -> [(String, Parse b)]
- Data.GraphViz: Params :: Bool -> [GlobalAttributes] -> ((n, nl) -> NodeCluster cl (n, l)) -> (cl -> GraphID) -> (cl -> [GlobalAttributes]) -> ((n, l) -> Attributes) -> ((n, n, el) -> Attributes) -> GraphvizParams n nl el cl l
+ Data.GraphViz: Params :: Bool -> [GlobalAttributes] -> ((n, nl) -> NodeCluster cl (n, l)) -> (cl -> Bool) -> (cl -> GraphID) -> (cl -> [GlobalAttributes]) -> ((n, l) -> Attributes) -> ((n, n, el) -> Attributes) -> GraphvizParams n nl el cl l
- Data.GraphViz.Attributes.Complete: FontNames :: Text -> Attribute
+ Data.GraphViz.Attributes.Complete: FontNames :: SVGFontNames -> Attribute
- Data.GraphViz.Attributes.Complete: Size :: Point -> Attribute
+ Data.GraphViz.Attributes.Complete: Size :: GraphSize -> Attribute
- Data.GraphViz.Attributes.Complete: Spline :: (Maybe Point) -> (Maybe Point) -> [Point] -> Spline
+ Data.GraphViz.Attributes.Complete: Spline :: Maybe Point -> Maybe Point -> [Point] -> Spline
- Data.GraphViz.Parsing: class ParseDot a where parse = optionalQuoted parseUnqt parseUnqtList = bracketSep (parseAndSpace $ character '[') (wrapWhitespace parseComma `onFail` whitespace1) (whitespace >> character ']') parseUnqt parseList = quotedParse parseUnqtList
+ Data.GraphViz.Parsing: class ParseDot a where parse = optionalQuoted parseUnqt parseUnqtList = bracketSep (parseAndSpace $ character '[') (wrapWhitespace parseComma `onFail` whitespace1) (whitespace *> character ']') parseUnqt parseList = quotedParse parseUnqtList
- Data.GraphViz.Types: class ParseDot a where parse = optionalQuoted parseUnqt parseUnqtList = bracketSep (parseAndSpace $ character '[') (wrapWhitespace parseComma `onFail` whitespace1) (whitespace >> character ']') parseUnqt parseList = quotedParse parseUnqtList
+ Data.GraphViz.Types: class ParseDot a where parse = optionalQuoted parseUnqt parseUnqtList = bracketSep (parseAndSpace $ character '[') (wrapWhitespace parseComma `onFail` whitespace1) (whitespace *> character ']') parseUnqt parseList = quotedParse parseUnqtList
- Data.GraphViz.Types.Graph: Cntxt :: !n -> !Maybe GraphID -> !Attributes -> ![(n, Attributes)] -> ![(n, Attributes)] -> Context n
+ Data.GraphViz.Types.Graph: Cntxt :: !n -> !(Maybe GraphID) -> !Attributes -> ![(n, Attributes)] -> ![(n, Attributes)] -> Context n
- Data.GraphViz.Types.Graph: inCluster :: Context n -> !Maybe GraphID
+ Data.GraphViz.Types.Graph: inCluster :: Context n -> !(Maybe GraphID)
Files
- Changelog +0/−637
- Changelog.md +687/−0
- Data/GraphViz.hs +17/−8
- Data/GraphViz/Algorithms/Clustering.hs +11/−11
- Data/GraphViz/Attributes/Colors.hs +32/−22
- Data/GraphViz/Attributes/Complete.hs +296/−188
- Data/GraphViz/Attributes/HTML.hs +49/−38
- Data/GraphViz/Attributes/Internal.hs +4/−6
- Data/GraphViz/Commands.hs +0/−3
- Data/GraphViz/Parsing.hs +84/−50
- Data/GraphViz/PreProcessing.hs +26/−33
- Data/GraphViz/Printing.hs +3/−1
- Data/GraphViz/Types/Canonical.hs +2/−3
- Data/GraphViz/Types/Common.hs +40/−45
- Data/GraphViz/Types/Generalised.hs +15/−16
- Data/GraphViz/Types/Graph.hs +6/−6
- FAQ +0/−644
- FAQ.md +632/−0
- LICENSE +0/−106
- LICENSE.md +100/−0
- README +0/−64
- README.md +58/−0
- TODO +0/−54
- TODO.md +48/−0
- graphviz.cabal +11/−9
- tests/Data/GraphViz/Testing/Instances/Attributes.hs +10/−0
- utils/AttributeGenerator.hs +391/−176
− Changelog
@@ -1,637 +0,0 @@-% Changelog-% Ivan Lazar Miljenovic--Release History and Changelog-=============================--The following is information about what major changes have gone into-each release.--Changes in 2999.14.1.0-------------------------* Add `isGraphvizInstalled` and `quitWithoutGraphviz` for programs to- test whether Graphviz has been installed (as previous attempts at- doing so via actual calls to dot, neato, etc. weren't working and- would be too verbose anyway).--Changes in 2999.14.0.0-------------------------* Added an instance of `Labellable` for strict `Text` values, as- requested by **Erik Rantapaa**.--Changes in 2999.13.0.3-------------------------* Allow usage of transformers-0.3.*. Spotted by **Peter Simons**.--Changes in 2999.13.0.2-------------------------* The `String` instance for `ToGraphID` requires the- `TypeSynonymInstances` pragma (at least on GHC < 7.4). Spotted by- **Gregory Guthrie**.--Changes in 2999.13.0.1-------------------------* Fixed Haddock typos.--Changes in 2999.13.0.0-------------------------* Added support for the `osage` and `patchwork` visualisation tools,- available as of Graphviz-2.28.0.--* Updated attributes as of Graphviz-2.28.0:-- - `SVG` colors are now supported, and the support for different- colors has been revamped.-- - `overlap=false` is now equivalent to `overlap=prism` and the- `RemoveOverlaps` option has been removed.-- - `LabelScheme` and `Rotation` are new attributes for use with- `sfdp`.-- - `Scale` is a new attribute for use with `twopi`.-- - Add new italics, bold, underline, superscript and subscript- options for HTML-like labels.-- - `LHeight` and `LWidth` for getting the height and width of the- root graph and clusters.--* Updated attributes from the current development branch of Graphviz- (i.e. 2.29.*). Please note that these will probably not work yet,- but are implemented now for future-proofing.-- - A new style for edges: `Tapered`.-- - `XLabel` allows you to specify labels external to a node or- edge. `ForceLabels` allow you to specify that these should be- drawn even when they will cause overlaps.-- - `ImagePath` allows you to specify where to search for images.-- - HTML-like labels now support `ID` values as well as horizontal- and vertical rules.-- - `BgColor` and `FillColor` now take a list of colors: this allows- gradient fills for graphs, clusters and nodes. The `Radial`- style and `GradientAngle` are also used for this purpose.-- - `FillColor` is now used by edges to set the color of any arrows.-- - [WebP](http://en.wikipedia.org/wiki/WebP) output support added.--* Other attribute changes:-- - Use a specified data type for the `Ordering` attribute rather- than an arbitrary `Text` value, and provide a documented wrapper- in `Data.GraphViz.Attributes`.-- - `Bb` has been renamed `BoundingBox`.-- - `ID` now only takes `EscString` (a type alias for `Text`) values- rather than arbitrary `Label`s.-- - The `Data.GraphViz.Attributes.HTML` module has had all values- re-named and is now meant to be imported qualified. It is also- no longer re-exported from `Data.GraphViz.Attributes.Complete`.--* The `ToGraphID` class provides a common wrapper to help create- cluster identifiers, etc.--* Cabal's `Test-Suite` functionality is now used. As part of this,- the `Data.GraphViz.Testing` module and sub-modules are no longer- exported by the library.--* The new `Benchmark` support in Cabal-1.14 is now used for the- benchmark script.--* Dropped support for base-3.--* The `Data.GraphViz.State` module is no longer exposed, as there's no- need for users to use it.--* Bugfixes:-- - Some corner cases in canonicalisation prevented it from being- idempotent.-- - The `TestParsing` script will no longer crash and refuse to- continue if an IO-based error (e.g. unable to successfully call- `dot`) occurs.-- - A typo was spotted by **Gabor Greif**.--Changes in 2999.12.0.4-------------------------* Parsing error messages have been cleared up, especially when parsing- Dot graphs. This came about from trying to help **Uri J. Braun**- with an error in his code (which took a while to diagnose as a- problem with the node type).--* Made more clear to people looking in `Data.GraphViz` who want to- create Dot graphs by hand to look in `Data.GraphViz.Types` (came- about when **Rustom Mody** stated he got confused trying to work out- how to do this).--* Fixed up augmentation; bug and fix spotted by **Max Rabkin**.--* Fix up the TestParsing script to actually use the new type setup.- It can also now take a single directory as an argument, and will try- to parse all (non-recursive) files in that directory.--Changes in 2999.12.0.3-------------------------* Fixes various mistakes in the Haddock documentation that slipped- through (either in the `String -> Text` conversion or adding new- modules and not checking their documentation thoroughly enough).--Changes in 2999.12.0.2-------------------------* Forgot to explicitly list the module for Arbitrary instance for the- graph representation.--Changes in 2999.12.0.1-------------------------* Fix a bug that prevented graphviz from being built with GHC 7.2.--Changes in 2999.12.0.0-------------------------Many large-level changes were done in this release; in rough-categories these are:--### Conversions from other types--* Can now more easily create Dot graphs from other graph-like data- structures with the new `graphElemsToDot` function, which takes a- list of nodes and edges.--* It is now no longer possible to use `graphToDot`, etc. to create Dot- graphs with anonymous clusters; all clusters must now have explicit- names (note that uniqueness is not enforced, and it is still- possible to directly create Dot graphs with anonymous clusters).--### Dot graph representations--* The canonical graph representation has been moved to its own module:- `Data.GraphViz.Types.Canonical`.--* The generalised representation has had all its "G" and "g" prefixes- removed.--* Two new representations:-- - `Data.GraphViz.Types.Graph` allows graph-like manipulation of- Dot code.-- - `Data.GraphViz.Types.Monadic` provides a monadic interface into- building relatively static graphs, based upon the- [_dotgen_](http://hackage.haskell.org/package/dotgen) library by- Andy Gill.--* The `DotRepr` class has been expanded, and three pseudo-classes have- been provided to reduce type-class contexts in type signatures.--### Using and manipulation Dot graphs--* Pure Haskell implementations of `dot -Tcanon` and `tred` are- available in `Data.GraphViz.Algorithms`.--* A new module is available for more direct low-level I/O with Dot- graphs, including the ability to run custom commands as opposed to- being limited to the standard dot, neato, etc.--### Attributes--* `Data.GraphViz.Attributes` now contains a slimmed-down recommended- list of attributes; the complete list can still be found in- `Data.GraphViz.Attributes.Complete`.--* The `charset` attribute is no longer available.--* Functions for specifying custom attributes (for pre-processors,- etc.) are available.--### Implementation--* Now uses [`Text`](http://hackage.haskell.org/package/text) values- rather than `String`s. Whilst performing this migration, the- improvements in speed for both printing and parsing improved- dramatically.-- - As part of this, human-readable Dot code is now produced by- default. As such, the `prettyPrint` and `prettyPrint'`- functions have been removed.--* Now uses state-based printing and parsing, so that things like graph- directedness, layer separators and color schemes can be taken into- account.--* Parsing large data-types (e.g. `Attributes`) now uses less- back-tracking.--* Now has a benchmarking script for testing printing and parsing- speed.--* Uses a custom exception type rather than a mish-mash of error,- `Maybe`, `Either`, exception types from used libraries, etc.--* Usage of UTF-8 is now enforced when doing I/O. If another encoding- is required, the `Text` value that's printed/parsed has to be- written/read from disk/network/etc. manually.--### Bug-Fixes--* The `Rects` `Attribute` should be able to take a list of `Rect`- values; error spotted by **Henning Gunther**.--* In some cases, global attribute names were being printed without- even an empty list (which doesn't match what dot, etc. expect).--Changes in 2999.11.0.0-------------------------* Addition of the `Labellable` class (and its method `toLabel`) to- make it easier to construct labels.--* Backslashes (i.e. the `\` character) are now escaped/unescaped- properly (bug spotted by **Han Joosten**). As part of this:-- - Dot-specific escapes such as `\N` are now also handled- correctly, so the slash does not need to be escaped.-- - Newline (`'\n'`) characters in labels, etc. are escaped to- centred-newlines in Dot code, but not unescaped.--* `Point` values can now have the optional third dimension and end in- a `!` to indicate that that position should be used (as input to- Graphviz).--* `LayerList` uses `LayerID` values, and now has a proper `shrink`- implementation in the test suite.--Changes in 2999.10.0.1-------------------------* Fixed a mistake in one of the source files that was made just to- make- [haskell-src-exts](http://hackage.haskell.org/package/haskell-src-exts)- happier.--* Fix the `Arbitrary` instance for `Point` in the testsuite (since- there's only one constructor now).--Changes in 2999.10.0.0-------------------------* Conversion of `FGL`-style graphs to `DotRepr` values is now achieved- using the new `GraphvizParams` configuration type. This allows us- to define a single parameter that stores all the conversion- functions to pass around rather than having to pass around several- functions. This also allows all the non-clustered and clustered- functions to be collapsed together, whereas what used to be handled- by the primed functions is now achieved by using the- `setDirectedness` function.-- There are three default `GraphvizParams` available:-- - `defaultParams` provides some sensible defaults (no attributes- or clustering).-- - `nonClusteredParams` is an alias of `defaultParams` where the- clustering type is explicitly set to be `()` for cases where you- don't want any clustering at all (whereas `defaultParams` allows- you to set your own clustering functions).-- - `blankParams` sets all fields to be `undefined`; this is useful- for situations where you have functions that will set some- values for you and there is no sensible default you can use- (mainly for the clustering function).--* Expansion of the `DotRepr` class:-- - More common functions are now defined as methods (`getID`,- etc.).-- - The ability to get more information about the structure of the- `DotRepr` graph, as well as where all the `DotNode`s are, etc.-- - `graphNodes` now returns `DotNode`s defined only as part of- `DotEdge`s, and will also merge duplicate `DotNode`s together.-- - `graphNodes` and `graphEdges` also return `GlobalAttributes`- that apply to them.--* The `Point` type now only has one constructor: `Point Double- Double`. The `Int`-only constructor was present due to historical- purposes and I thought that the `Pos` value for a `DotNode` would- always be a pair of `Int`s; this turns out not to be the case.--* `SortV` and `PrismOverlap` now only take `Word16` values rather than- `Int`s, as they're not meant to allow negative values (the choice of- using `Word16` rather than `Word` was arbitrary, and because it's- unlikely those values will be large enough to require the larger- values available in `Word`).--* `NodeCluster` has been generalised to not have to take an `LNode`- for the node type; the type alias `LNodeCluster` is available if you- still want this.--* Several documentation typos fixed, including one spotted by **Kevin- Quick**.--* The test-suite now allows running individual tests.--Changes in 2999.9.0.0------------------------* graphviz now has an FAQ and an improved README as well as its own- [homepage](http://projects.haskell.org/graphviz/).--* Canonicalisation of `DotRepr` values is now available with the- `canonicalise` function.--* Add support for record labels; values are automatically- escaped/unescaped. The `Record` and `MRecord` shapes have been- added for use with these labels. **Requested by Minh Thu and Eric- Kow.**--* Add support for HTML-like values (this replaces the wrong and- completely broken URL datatype). Strings are automatically- escaped/unescaped.--* Named `PortPos` values are now accepted (as required for record and- HTML-like labels).--* `GraphID` no longer allows HTML-like values (since Graphviz doesn't- seem to allow it).--* `RankSep` takes a list of `Double` values as required.--* `Attribute` has a new constructor `UnknownAttribute` for use when- parsing deprecated Graphviz attributes in old Dot code.--* Various parsing fixes; of special note:-- - Statements no longer need to end in a semi-colon;-- - Anonymous sub-graphs are now supported.-- - Edge statements can now handle node groupings (e.g. ` a -> {b- c}`) as well as `portPos` values (e.g. `a:from -> b:to`).-- - Unquoted `String`s containing non-ASCII characters are now- parsed properly (though they are assumed to be encoded with- UTF-8). **Thanks to Jules Bean (aka quicksilver) for working- out how to do this.**-- More specifically: almost all Dot files that ship with Graphviz, as- documentation in the Linux kernel, etc. are now parseable.--* A new script to assist in testing whether "real-world" Dot graphs- are parseable.--* Slight performance increase when parsing: whereas parsing is done- case-insensitively, the "correct" case is now checked by default- which has a moderate affect on parsing times.--* Split lines are now able to be handled when parsing.--Changes in 2999.8.0.0------------------------* Added support for generalised `DotGraph`s; this optional- representation removes the restriction of ordering of Dot- statements. This allows for greater flexibility of how to specify- Dot code. As an offshoot from this, most relevant functions now- utilise a new `DotRepr` class that work with both `DotGraph`s and- the new `GDotGraph`s; this shouldn't affect any code already in use.--* With the **prompting of Noam Lewis**, the augmentation functions- have been revamped in two ways:-- - Now contains support for multiple edges.-- - The ability to perform "manual" augmentation if greater control is- desired.--* Add a preview function to quickly render and visualise an `FGL`- graph using the `Xlib` canvas.--* Added a pseudo-inverse of the `FGL -> Dot` functions (a graph is- created, but the original node and edge labels are unrecoverable).--* The `Printing` and `Parsing` modules have been moved (from- `Data.GraphViz.Types` to `Data.GraphViz`).--* Reworked file-generating commands such that they return the filename- of the created file if successful.--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-- [colour]: http://www.haskell.org/haskellwiki/Colour--* 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------------------------* Remove some `Shape` aliases and change capitalisation of others.--* Properly parse and print IDs of clusters.--* Allow `NodeCluster` values to have node types different from the- `LNode` they come from.--Changes in 2999.5.1.1------------------------* When used as labels, etc., the Dot keywords `node`, `edge`, `graph`,- `digraph`, `subgraph`, and `strict` need to be quoted. **Spotted by- Kathleen Fisher.**--Changes in 2999.5.1.0------------------------* Potentially fixed the `graphvizWithHandle` bug; correct approach- **spotted by Nikolas Mayr**.--* Fixed up `Parsing` of various `Attribute` sub-values, especially- `Point` and `Spline` (and hence `Pos`, which uses them).--* Pre-process out comments and join together multi-line strings before- parsing.--* Properly parse `Doubles` like `".2"`.--Changes in 2999.5.0.0------------------------A major re-write occured; these are the highlights:--* Re-write parsing and printing of Dot code using the new `ParseDot`- and `PrintDot` classes. This should finally fix all quoting issues,- as well as leaving `Show` as the code representation for hacking- purposes. As part of this, the `Data.GraphViz.ParserCombinators`- module has been moved to `Data.GraphViz.Types.Parsing`.--* Re-write the various `Dot*` datatypes in `Data.GraphViz.Types`.- Sub-graphs/clusters are now their own entity rather than being part- of `DotNode` and the Node ID type is now a type parameter rather- than being just `Int`. Sub-graphs/clusters can now also be parsed.--* The various conversion functions in `Data.GraphViz` now come in two- flavours: the unprimed versions take in a `Bool` indicating if the- graph is directed or not; the primed versions attempt to- automatically detect this.--* Add cluster support for the graph augmentation functions, **as- requested by Nikolas Mayr**.--* Allow custom arrow types as supported by GraphViz; **as requested by- Han Joosten**.--* Fixed a bug in HSV-style `Color` values where `Int` was used instead of- `Double`; **spotted by Michael deLorimier**.--* Properly resolved the situation initially spotted by Neil Brown:- Matthew Sackman was following Dot terminology for an edge `a -> b`- when using _head_ for `b` and _tail_ for `a` (this is presumably- because the head/tail of the arrow are at those nodes). `DotEdge`- now uses _from_ and _to_ avoid ambiguity; the various `Attribute`- values still follow upstream usage.--Changes in 2999.1.0.2------------------------* Fix a bug **spotted by Srihari Ramanathan** where `Color` values- were double-quoted.--Changes in 2999.1.0.1------------------------* The `Color` `Attribute` should take `[Color]`, not just a single- `Color`.--Changes in 2999.1.0.0------------------------* Stop using `Either` for composite `Attributes` and use a custom- type: this avoids problems with the `Show` instance.--Changes in 2999.0.0.0------------------------* Fixed a bug where the Show instance and read function for `DotEdge`- had the from/to nodes the wrong way round. This was not immediately- noticed since the `Graph` to `DotGraph` functions created them the- wrong way round, so for those users who only used these this was not- apparent. **Spotted by Neil Brown.**--* Greatly improved `Attribute` usage: almost all attributes are now- covered with allowed values.--* Extend DotGraph to include whether a graph is strict or not and if- it has an ID. Also move the directedGraph field.--* Make `Dot` refer to the actual dot command and `DotArrow` refer to- the `ArrowType` (rather than `DotCmd` and `Dot` as before).--* Make the `Data.GraphViz.ParserCombinators` module available to end- users again, but not re-exported by `Data.GraphViz`; it has a- warning message up the top not to be used. It is there purely for- documentative purposes.--* Use [extensible-exceptions] so that `base-3.x` is once again- supported.-- [extensible-exceptions]: http://hackage.haskell.org/package/extensible-exceptions--* Follow the [Package Versioning Policy] rather than using dates for- versions.-- [Package Versioning Policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy---Changes in 2009.5.1----------------------* New maintainer: Ivan Lazar Miljenovic.--* Support `polyparse >= 1.1` (as opposed to `< 1.3`)--* Require `base == 4.*` (i.e. `GHC 6.10.*`) due to new exception handling.--* Include functions from [Graphalyze-0.5] for running GraphViz- commands, etc.-- [Graphalyze-0.5]: http://hackage.haskell.org/package/Graphalyze-0.5--* Module re-organisation.--* The `Data.GraphViz.ParserCombinators` module is no longer available- to end users.--* Improved Haddock documentation.--Changes in 2008.9.20-----------------------* Differentiate between undirected and directed graphs (previously- only directed graphs were supported).--* Clustering support was added.--Older versions-----------------For versions of graphviz older than `2008.9.20`, the exact differences-between versions is unknown.--<!--- Local Variables:- mode:markdown- End:- -->
+ Changelog.md view
@@ -0,0 +1,687 @@+% Changelog+% Ivan Lazar Miljenovic++Release History and Changelog+=============================++The following is information about what major changes have gone into+each release.++Changes in 2999.15.0.0+----------------------++* The repository is now hosted on+ [hub.darcs.net](http://hub.darcs.net/ivanm/graphviz), and using the+ bug-tracker there.++* Updates to various `Attribute` definitions:++ - The list of available shapes has been expanded to take into+ account the new synthetic biology shapes.++ - The `Size` and `FontNames` attributes now have specified data types.++ - The optional start and end points for `Spline`s were previously+ the wrong way round; this has now been fixed.++ - Explicitly only print 2-dimensional `Point` values for `Rect`+ and `DPoint` (previously only 2-dimensional values where parsed,+ but it was possible to print a 3-dimensional value).++ - HTML-like labels previously disallowed empty textual label+ components when parsing; spotted by **Daniel Hummel**.++* `GraphvizParams` now lets you specify whether a "cluster" is+ actually a cluster or a sub-graph. Requested by **Gabor Greif**.++* Fixed an error where printing edges whose attributes contained a+ `ColorScheme` attribute, that attribute would stay in the state and+ the old color scheme would override the _parent's_ state.++* Previously, some malformed attributes were accepted when being+ parsed as they silently became parsed as an `UnknownAttribute`.+ Now, attributes where the attribute name and the equal sign are+ successfully parsed **but** the value of the attribute is _not_+ successfully parse will throw an unrecoverable error.++ **Note**: this does mean that some Dot graphs that are accepted by+ Graphviz (as they separate tokenizing from parsing; as such+ something like `"0.1"` is successfully accepted as an integer,+ specifically `0`) are no longer accepted when parsing them in.++* Miscellaneous parsing improvements:++ - Whilst not specified anywhere, Graphviz seems to treat empty+ quotes as values for attributes expecting a number as their+ default; as such, this is now taken into account when parsing.++ - `DPoint` values can now parse an optional `+` prefix.++ - Whitespaces after commas in HSV colors are now accepted.++* Error messages from parsing are improved to help you track down+ where the parsing error occurred (in that it's easier to find which+ attribute failed to parse, etc.).++Changes in 2999.14.1.0+----------------------++* Add `isGraphvizInstalled` and `quitWithoutGraphviz` for programs to+ test whether Graphviz has been installed (as previous attempts at+ doing so via actual calls to dot, neato, etc. weren't working and+ would be too verbose anyway).++Changes in 2999.14.0.0+----------------------++* Added an instance of `Labellable` for strict `Text` values, as+ requested by **Erik Rantapaa**.++Changes in 2999.13.0.3+----------------------++* Allow usage of transformers-0.3.*. Spotted by **Peter Simons**.++Changes in 2999.13.0.2+----------------------++* The `String` instance for `ToGraphID` requires the+ `TypeSynonymInstances` pragma (at least on GHC < 7.4). Spotted by+ **Gregory Guthrie**.++Changes in 2999.13.0.1+----------------------++* Fixed Haddock typos.++Changes in 2999.13.0.0+----------------------++* Added support for the `osage` and `patchwork` visualisation tools,+ available as of Graphviz-2.28.0.++* Updated attributes as of Graphviz-2.28.0:++ - `SVG` colors are now supported, and the support for different+ colors has been revamped.++ - `overlap=false` is now equivalent to `overlap=prism` and the+ `RemoveOverlaps` option has been removed.++ - `LabelScheme` and `Rotation` are new attributes for use with+ `sfdp`.++ - `Scale` is a new attribute for use with `twopi`.++ - Add new italics, bold, underline, superscript and subscript+ options for HTML-like labels.++ - `LHeight` and `LWidth` for getting the height and width of the+ root graph and clusters.++* Updated attributes from the current development branch of Graphviz+ (i.e. 2.29.*). Please note that these will probably not work yet,+ but are implemented now for future-proofing.++ - A new style for edges: `Tapered`.++ - `XLabel` allows you to specify labels external to a node or+ edge. `ForceLabels` allow you to specify that these should be+ drawn even when they will cause overlaps.++ - `ImagePath` allows you to specify where to search for images.++ - HTML-like labels now support `ID` values as well as horizontal+ and vertical rules.++ - `BgColor` and `FillColor` now take a list of colors: this allows+ gradient fills for graphs, clusters and nodes. The `Radial`+ style and `GradientAngle` are also used for this purpose.++ - `FillColor` is now used by edges to set the color of any arrows.++ - [WebP](http://en.wikipedia.org/wiki/WebP) output support added.++* Other attribute changes:++ - Use a specified data type for the `Ordering` attribute rather+ than an arbitrary `Text` value, and provide a documented wrapper+ in `Data.GraphViz.Attributes`.++ - `Bb` has been renamed `BoundingBox`.++ - `ID` now only takes `EscString` (a type alias for `Text`) values+ rather than arbitrary `Label`s.++ - The `Data.GraphViz.Attributes.HTML` module has had all values+ re-named and is now meant to be imported qualified. It is also+ no longer re-exported from `Data.GraphViz.Attributes.Complete`.++* The `ToGraphID` class provides a common wrapper to help create+ cluster identifiers, etc.++* Cabal's `Test-Suite` functionality is now used. As part of this,+ the `Data.GraphViz.Testing` module and sub-modules are no longer+ exported by the library.++* The new `Benchmark` support in Cabal-1.14 is now used for the+ benchmark script.++* Dropped support for base-3.++* The `Data.GraphViz.State` module is no longer exposed, as there's no+ need for users to use it.++* Bugfixes:++ - Some corner cases in canonicalisation prevented it from being+ idempotent.++ - The `TestParsing` script will no longer crash and refuse to+ continue if an IO-based error (e.g. unable to successfully call+ `dot`) occurs.++ - A typo was spotted by **Gabor Greif**.++Changes in 2999.12.0.4+----------------------++* Parsing error messages have been cleared up, especially when parsing+ Dot graphs. This came about from trying to help **Uri J. Braun**+ with an error in his code (which took a while to diagnose as a+ problem with the node type).++* Made more clear to people looking in `Data.GraphViz` who want to+ create Dot graphs by hand to look in `Data.GraphViz.Types` (came+ about when **Rustom Mody** stated he got confused trying to work out+ how to do this).++* Fixed up augmentation; bug and fix spotted by **Max Rabkin**.++* Fix up the TestParsing script to actually use the new type setup.+ It can also now take a single directory as an argument, and will try+ to parse all (non-recursive) files in that directory.++Changes in 2999.12.0.3+----------------------++* Fixes various mistakes in the Haddock documentation that slipped+ through (either in the `String -> Text` conversion or adding new+ modules and not checking their documentation thoroughly enough).++Changes in 2999.12.0.2+----------------------++* Forgot to explicitly list the module for Arbitrary instance for the+ graph representation.++Changes in 2999.12.0.1+----------------------++* Fix a bug that prevented graphviz from being built with GHC 7.2.++Changes in 2999.12.0.0+----------------------++Many large-level changes were done in this release; in rough+categories these are:++### Conversions from other types++* Can now more easily create Dot graphs from other graph-like data+ structures with the new `graphElemsToDot` function, which takes a+ list of nodes and edges.++* It is now no longer possible to use `graphToDot`, etc. to create Dot+ graphs with anonymous clusters; all clusters must now have explicit+ names (note that uniqueness is not enforced, and it is still+ possible to directly create Dot graphs with anonymous clusters).++### Dot graph representations++* The canonical graph representation has been moved to its own module:+ `Data.GraphViz.Types.Canonical`.++* The generalised representation has had all its "G" and "g" prefixes+ removed.++* Two new representations:++ - `Data.GraphViz.Types.Graph` allows graph-like manipulation of+ Dot code.++ - `Data.GraphViz.Types.Monadic` provides a monadic interface into+ building relatively static graphs, based upon the+ [_dotgen_](http://hackage.haskell.org/package/dotgen) library by+ Andy Gill.++* The `DotRepr` class has been expanded, and three pseudo-classes have+ been provided to reduce type-class contexts in type signatures.++### Using and manipulation Dot graphs++* Pure Haskell implementations of `dot -Tcanon` and `tred` are+ available in `Data.GraphViz.Algorithms`.++* A new module is available for more direct low-level I/O with Dot+ graphs, including the ability to run custom commands as opposed to+ being limited to the standard dot, neato, etc.++### Attributes++* `Data.GraphViz.Attributes` now contains a slimmed-down recommended+ list of attributes; the complete list can still be found in+ `Data.GraphViz.Attributes.Complete`.++* The `charset` attribute is no longer available.++* Functions for specifying custom attributes (for pre-processors,+ etc.) are available.++### Implementation++* Now uses [`Text`](http://hackage.haskell.org/package/text) values+ rather than `String`s. Whilst performing this migration, the+ improvements in speed for both printing and parsing improved+ dramatically.++ - As part of this, human-readable Dot code is now produced by+ default. As such, the `prettyPrint` and `prettyPrint'`+ functions have been removed.++* Now uses state-based printing and parsing, so that things like graph+ directedness, layer separators and color schemes can be taken into+ account.++* Parsing large data-types (e.g. `Attributes`) now uses less+ back-tracking.++* Now has a benchmarking script for testing printing and parsing+ speed.++* Uses a custom exception type rather than a mish-mash of error,+ `Maybe`, `Either`, exception types from used libraries, etc.++* Usage of UTF-8 is now enforced when doing I/O. If another encoding+ is required, the `Text` value that's printed/parsed has to be+ written/read from disk/network/etc. manually.++### Bug-Fixes++* The `Rects` `Attribute` should be able to take a list of `Rect`+ values; error spotted by **Henning Gunther**.++* In some cases, global attribute names were being printed without+ even an empty list (which doesn't match what dot, etc. expect).++Changes in 2999.11.0.0+----------------------++* Addition of the `Labellable` class (and its method `toLabel`) to+ make it easier to construct labels.++* Backslashes (i.e. the `\` character) are now escaped/unescaped+ properly (bug spotted by **Han Joosten**). As part of this:++ - Dot-specific escapes such as `\N` are now also handled+ correctly, so the slash does not need to be escaped.++ - Newline (`'\n'`) characters in labels, etc. are escaped to+ centred-newlines in Dot code, but not unescaped.++* `Point` values can now have the optional third dimension and end in+ a `!` to indicate that that position should be used (as input to+ Graphviz).++* `LayerList` uses `LayerID` values, and now has a proper `shrink`+ implementation in the test suite.++Changes in 2999.10.0.1+----------------------++* Fixed a mistake in one of the source files that was made just to+ make+ [haskell-src-exts](http://hackage.haskell.org/package/haskell-src-exts)+ happier.++* Fix the `Arbitrary` instance for `Point` in the testsuite (since+ there's only one constructor now).++Changes in 2999.10.0.0+----------------------++* Conversion of `FGL`-style graphs to `DotRepr` values is now achieved+ using the new `GraphvizParams` configuration type. This allows us+ to define a single parameter that stores all the conversion+ functions to pass around rather than having to pass around several+ functions. This also allows all the non-clustered and clustered+ functions to be collapsed together, whereas what used to be handled+ by the primed functions is now achieved by using the+ `setDirectedness` function.++ There are three default `GraphvizParams` available:++ - `defaultParams` provides some sensible defaults (no attributes+ or clustering).++ - `nonClusteredParams` is an alias of `defaultParams` where the+ clustering type is explicitly set to be `()` for cases where you+ don't want any clustering at all (whereas `defaultParams` allows+ you to set your own clustering functions).++ - `blankParams` sets all fields to be `undefined`; this is useful+ for situations where you have functions that will set some+ values for you and there is no sensible default you can use+ (mainly for the clustering function).++* Expansion of the `DotRepr` class:++ - More common functions are now defined as methods (`getID`,+ etc.).++ - The ability to get more information about the structure of the+ `DotRepr` graph, as well as where all the `DotNode`s are, etc.++ - `graphNodes` now returns `DotNode`s defined only as part of+ `DotEdge`s, and will also merge duplicate `DotNode`s together.++ - `graphNodes` and `graphEdges` also return `GlobalAttributes`+ that apply to them.++* The `Point` type now only has one constructor: `Point Double+ Double`. The `Int`-only constructor was present due to historical+ purposes and I thought that the `Pos` value for a `DotNode` would+ always be a pair of `Int`s; this turns out not to be the case.++* `SortV` and `PrismOverlap` now only take `Word16` values rather than+ `Int`s, as they're not meant to allow negative values (the choice of+ using `Word16` rather than `Word` was arbitrary, and because it's+ unlikely those values will be large enough to require the larger+ values available in `Word`).++* `NodeCluster` has been generalised to not have to take an `LNode`+ for the node type; the type alias `LNodeCluster` is available if you+ still want this.++* Several documentation typos fixed, including one spotted by **Kevin+ Quick**.++* The test-suite now allows running individual tests.++Changes in 2999.9.0.0+---------------------++* graphviz now has an FAQ and an improved README as well as its own+ [homepage](http://projects.haskell.org/graphviz/).++* Canonicalisation of `DotRepr` values is now available with the+ `canonicalise` function.++* Add support for record labels; values are automatically+ escaped/unescaped. The `Record` and `MRecord` shapes have been+ added for use with these labels. **Requested by Minh Thu and Eric+ Kow.**++* Add support for HTML-like values (this replaces the wrong and+ completely broken URL datatype). Strings are automatically+ escaped/unescaped.++* Named `PortPos` values are now accepted (as required for record and+ HTML-like labels).++* `GraphID` no longer allows HTML-like values (since Graphviz doesn't+ seem to allow it).++* `RankSep` takes a list of `Double` values as required.++* `Attribute` has a new constructor `UnknownAttribute` for use when+ parsing deprecated Graphviz attributes in old Dot code.++* Various parsing fixes; of special note:++ - Statements no longer need to end in a semi-colon;++ - Anonymous sub-graphs are now supported.++ - Edge statements can now handle node groupings (e.g. ` a -> {b+ c}`) as well as `portPos` values (e.g. `a:from -> b:to`).++ - Unquoted `String`s containing non-ASCII characters are now+ parsed properly (though they are assumed to be encoded with+ UTF-8). **Thanks to Jules Bean (aka quicksilver) for working+ out how to do this.**++ More specifically: almost all Dot files that ship with Graphviz, as+ documentation in the Linux kernel, etc. are now parseable.++* A new script to assist in testing whether "real-world" Dot graphs+ are parseable.++* Slight performance increase when parsing: whereas parsing is done+ case-insensitively, the "correct" case is now checked by default+ which has a moderate affect on parsing times.++* Split lines are now able to be handled when parsing.++Changes in 2999.8.0.0+---------------------++* Added support for generalised `DotGraph`s; this optional+ representation removes the restriction of ordering of Dot+ statements. This allows for greater flexibility of how to specify+ Dot code. As an offshoot from this, most relevant functions now+ utilise a new `DotRepr` class that work with both `DotGraph`s and+ the new `GDotGraph`s; this shouldn't affect any code already in use.++* With the **prompting of Noam Lewis**, the augmentation functions+ have been revamped in two ways:++ - Now contains support for multiple edges.++ - The ability to perform "manual" augmentation if greater control is+ desired.++* Add a preview function to quickly render and visualise an `FGL`+ graph using the `Xlib` canvas.++* Added a pseudo-inverse of the `FGL -> Dot` functions (a graph is+ created, but the original node and edge labels are unrecoverable).++* The `Printing` and `Parsing` modules have been moved (from+ `Data.GraphViz.Types` to `Data.GraphViz`).++* Reworked file-generating commands such that they return the filename+ of the created file if successful.++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++ [colour]: http://www.haskell.org/haskellwiki/Colour++* 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+---------------------++* Remove some `Shape` aliases and change capitalisation of others.++* Properly parse and print IDs of clusters.++* Allow `NodeCluster` values to have node types different from the+ `LNode` they come from.++Changes in 2999.5.1.1+---------------------++* When used as labels, etc., the Dot keywords `node`, `edge`, `graph`,+ `digraph`, `subgraph`, and `strict` need to be quoted. **Spotted by+ Kathleen Fisher.**++Changes in 2999.5.1.0+---------------------++* Potentially fixed the `graphvizWithHandle` bug; correct approach+ **spotted by Nikolas Mayr**.++* Fixed up `Parsing` of various `Attribute` sub-values, especially+ `Point` and `Spline` (and hence `Pos`, which uses them).++* Pre-process out comments and join together multi-line strings before+ parsing.++* Properly parse `Doubles` like `".2"`.++Changes in 2999.5.0.0+---------------------++A major re-write occured; these are the highlights:++* Re-write parsing and printing of Dot code using the new `ParseDot`+ and `PrintDot` classes. This should finally fix all quoting issues,+ as well as leaving `Show` as the code representation for hacking+ purposes. As part of this, the `Data.GraphViz.ParserCombinators`+ module has been moved to `Data.GraphViz.Types.Parsing`.++* Re-write the various `Dot*` datatypes in `Data.GraphViz.Types`.+ Sub-graphs/clusters are now their own entity rather than being part+ of `DotNode` and the Node ID type is now a type parameter rather+ than being just `Int`. Sub-graphs/clusters can now also be parsed.++* The various conversion functions in `Data.GraphViz` now come in two+ flavours: the unprimed versions take in a `Bool` indicating if the+ graph is directed or not; the primed versions attempt to+ automatically detect this.++* Add cluster support for the graph augmentation functions, **as+ requested by Nikolas Mayr**.++* Allow custom arrow types as supported by GraphViz; **as requested by+ Han Joosten**.++* Fixed a bug in HSV-style `Color` values where `Int` was used instead of+ `Double`; **spotted by Michael deLorimier**.++* Properly resolved the situation initially spotted by Neil Brown:+ Matthew Sackman was following Dot terminology for an edge `a -> b`+ when using _head_ for `b` and _tail_ for `a` (this is presumably+ because the head/tail of the arrow are at those nodes). `DotEdge`+ now uses _from_ and _to_ avoid ambiguity; the various `Attribute`+ values still follow upstream usage.++Changes in 2999.1.0.2+---------------------++* Fix a bug **spotted by Srihari Ramanathan** where `Color` values+ were double-quoted.++Changes in 2999.1.0.1+---------------------++* The `Color` `Attribute` should take `[Color]`, not just a single+ `Color`.++Changes in 2999.1.0.0+---------------------++* Stop using `Either` for composite `Attributes` and use a custom+ type: this avoids problems with the `Show` instance.++Changes in 2999.0.0.0+---------------------++* Fixed a bug where the Show instance and read function for `DotEdge`+ had the from/to nodes the wrong way round. This was not immediately+ noticed since the `Graph` to `DotGraph` functions created them the+ wrong way round, so for those users who only used these this was not+ apparent. **Spotted by Neil Brown.**++* Greatly improved `Attribute` usage: almost all attributes are now+ covered with allowed values.++* Extend DotGraph to include whether a graph is strict or not and if+ it has an ID. Also move the directedGraph field.++* Make `Dot` refer to the actual dot command and `DotArrow` refer to+ the `ArrowType` (rather than `DotCmd` and `Dot` as before).++* Make the `Data.GraphViz.ParserCombinators` module available to end+ users again, but not re-exported by `Data.GraphViz`; it has a+ warning message up the top not to be used. It is there purely for+ documentative purposes.++* Use [extensible-exceptions] so that `base-3.x` is once again+ supported.++ [extensible-exceptions]: http://hackage.haskell.org/package/extensible-exceptions++* Follow the [Package Versioning Policy] rather than using dates for+ versions.++ [Package Versioning Policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy+++Changes in 2009.5.1+-------------------++* New maintainer: Ivan Lazar Miljenovic.++* Support `polyparse >= 1.1` (as opposed to `< 1.3`)++* Require `base == 4.*` (i.e. `GHC 6.10.*`) due to new exception handling.++* Include functions from [Graphalyze-0.5] for running GraphViz+ commands, etc.++ [Graphalyze-0.5]: http://hackage.haskell.org/package/Graphalyze-0.5++* Module re-organisation.++* The `Data.GraphViz.ParserCombinators` module is no longer available+ to end users.++* Improved Haddock documentation.++Changes in 2008.9.20+--------------------++* Differentiate between undirected and directed graphs (previously+ only directed graphs were supported).++* Clustering support was added.++Older versions+--------------++For versions of graphviz older than `2008.9.20`, the exact differences+between versions is unknown.
Data/GraphViz.hs view
@@ -75,6 +75,7 @@ import Data.GraphViz.Commands import Data.GraphViz.Commands.IO(hGetDot) +import Data.Functor((<$>)) import Data.Graph.Inductive.Graph import qualified Data.Set as Set import Control.Arrow((&&&), first)@@ -82,7 +83,6 @@ import qualified Data.Map as Map import qualified Data.Text.Lazy as T import Data.Text.Lazy(Text)-import Control.Monad(liftM) import System.IO.Unsafe(unsafePerformIO) import Control.Concurrent(forkIO) @@ -169,6 +169,11 @@ -- These correspond to 'LNode' and 'LEdge' in FGL graphs. -- -- The clustering in 'clusterBy' can be to arbitrary depth.+--+-- Note that the term \"cluster\" is slightly conflated here: in+-- terms of @GraphvizParams@ values, a cluster is a grouping of+-- nodes; the 'isDotCluster' function lets you specify whether it is+-- a cluster in the Dot sense or just a sub-graph. data GraphvizParams n nl el cl l = Params { -- | @True@ if the graph is directed; @False@ -- otherwise.@@ -179,6 +184,9 @@ -- | A function to specify which cluster a particular -- node is in. , clusterBy :: ((n,nl) -> NodeCluster cl (n,l))+ -- | Is this \"cluster\" actually a cluster, or just a+ -- sub-graph?+ , isDotCluster :: (cl -> Bool) -- | The name/identifier for a cluster. , clusterID :: (cl -> GraphID) -- | Specify which global attributes are applied in@@ -208,6 +216,7 @@ defaultParams = Params { isDirected = True , globalAttributes = [] , clusterBy = N+ , isDotCluster = const True , clusterID = const (Int 0) , fmtCluster = const [] , fmtNode = const []@@ -232,6 +241,7 @@ blankParams = Params { isDirected = undefined , globalAttributes = undefined , clusterBy = undefined+ , isDotCluster = undefined , clusterID = undefined , fmtCluster = undefined , fmtNode = undefined@@ -271,8 +281,8 @@ , nodeStmts = ns , edgeStmts = es }- (cs, ns) = clustersToNodes (clusterBy params) (clusterID params)- (fmtCluster params) (fmtNode params)+ (cs, ns) = clustersToNodes (clusterBy params) (isDotCluster params)+ (clusterID params) (fmtCluster params) (fmtNode params) lns es = mapMaybe mkDotEdge les mkDotEdge e@(f,t,_) = if dirGraph || f <= t@@ -294,7 +304,7 @@ -- Applying uniqBy just in case... ns = uniqBy fst . map toLN $ graphNodes dg es = concatMap toLE $ graphEdges dg- -- Need to ensure that for some reason there are node IDs in an+ -- Need to check that for some reason there aren't node IDs in an -- edge but not on their own. nSet = Set.fromList $ map fst ns nEs = map (flip (,) [])@@ -415,8 +425,8 @@ es' = zipWith addID es ([1..] :: [Int]) addID (f,t,l) i = (f,t,EID (T.pack $ show i) l) --- | Add the 'Comment' to the list of attributes containing the value--- of the unique edge identifier.+-- | Add a custom attribute to the list of attributes containing the+-- value of the unique edge identifier. setEdgeIDAttribute :: (LEdge el -> Attributes) -> (LEdge (EdgeID el) -> Attributes) setEdgeIDAttribute f = \ e@(_,_,eid) -> identifierAttribute (eID eid)@@ -437,8 +447,7 @@ dotAttributes :: (Graph gr, PPDotRepr dg Node) => Bool -> gr nl (EdgeID el) -> dg Node -> IO (gr (AttributeNode nl) (AttributeEdge el)) dotAttributes isDir gr dot- = liftM (augmentGraph gr . parseDG)- $ graphvizWithHandle command dot DotOutput hGetDot+ = augmentGraph gr . parseDG <$> graphvizWithHandle command dot DotOutput hGetDot where parseDG = (`asTypeOf` dot) command = if isDir then dirCommand else undirCommand
Data/GraphViz/Algorithms/Clustering.hs view
@@ -32,11 +32,11 @@ -- | Extract the clusters and nodes from the list of nodes. clustersToNodes :: (Ord c) => ((n,a) -> NodeCluster c (n,l))- -> (c -> GraphID) -> (c -> [GlobalAttributes])+ -> (c -> Bool) -> (c -> GraphID) -> (c -> [GlobalAttributes]) -> ((n,l) -> Attributes) -> [(n,a)] -> ([DotSubGraph n], [DotNode n])-clustersToNodes clusterBy cID fmtCluster fmtNode- = treesToDot cID fmtCluster fmtNode+clustersToNodes clusterBy isC cID fmtCluster fmtNode+ = treesToDot isC cID fmtCluster fmtNode . collapseNClusts . map (clustToTree . clusterBy) @@ -84,23 +84,23 @@ -- | Convert the cluster representation of the trees into 'DotNode's -- and 'DotSubGraph's (with @'isCluster' = 'True'@, and -- @'subGraphID' = 'Nothing'@).-treesToDot :: (c -> GraphID) -> (c -> [GlobalAttributes])+treesToDot :: (c -> Bool) -> (c -> GraphID) -> (c -> [GlobalAttributes]) -> ((n,a) -> Attributes) -> [ClusterTree c (n,a)] -> ([DotSubGraph n], [DotNode n])-treesToDot cID fmtCluster fmtNode+treesToDot isC cID fmtCluster fmtNode = partitionEithers- . map (treeToDot cID fmtCluster fmtNode)+ . map (treeToDot isC cID fmtCluster fmtNode) -- | Convert this 'ClusterTree' into its /Dot/ representation.-treeToDot :: (c -> GraphID) -> (c -> [GlobalAttributes])+treeToDot :: (c -> Bool) -> (c -> GraphID) -> (c -> [GlobalAttributes]) -> ((n,a) -> Attributes) -> ClusterTree c (n,a) -> Either (DotSubGraph n) (DotNode n)-treeToDot _ _ fmtNode (NT ln)+treeToDot _ _ _ fmtNode (NT ln) = Right DotNode { nodeID = fst ln , nodeAttributes = fmtNode ln }-treeToDot cID fmtCluster fmtNode (CT c nts)- = Left DotSG { isCluster = True+treeToDot isC cID fmtCluster fmtNode (CT c nts)+ = Left DotSG { isCluster = isC c , subGraphID = Just $ cID c , subGraphStmts = stmts }@@ -110,4 +110,4 @@ , nodeStmts = ns , edgeStmts = [] }- (cs, ns) = treesToDot cID fmtCluster fmtNode nts+ (cs, ns) = treesToDot isC cID fmtCluster fmtNode nts
Data/GraphViz/Attributes/Colors.hs view
@@ -52,7 +52,6 @@ import Data.Maybe(isJust) import Data.Word(Word8) import qualified Data.Text.Lazy as T-import Control.Monad(liftM) -- ----------------------------------------------------------------------------- @@ -122,6 +121,8 @@ , parseNC (undefined :: SVGColor) False , parseX11Color False ]+ `onFail`+ fail "Could not parse Color" where parseHexBased = do character '#'@@ -132,13 +133,12 @@ _ -> throw . NotDotCode $ "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 ","+ parseHSV = HSV <$> parse+ <* parseSep+ <*> parse+ <* parseSep+ <*> parse+ parseSep = oneOf [ string "," *> whitespace , whitespace1 ] parse2Hex = do c1 <- satisfy isHexDigit@@ -152,10 +152,16 @@ , parseNC (undefined :: SVGColor) True , parseX11Color True ]+ `onFail`+ fail "Could not parse Color" parseUnqtList = sepBy1 parseUnqt (character ':')+ `onFail`+ do cs <- getColorScheme+ failBad $ "Error parsing list of Colors with color scheme of "+ ++ show cs - parseList = liftM (:[])+ parseList = fmap (:[]) -- Unquoted single color (oneOf [ parseNC (undefined :: BrewerColor) True , parseNC (undefined :: SVGColor) True@@ -164,6 +170,10 @@ ) `onFail` quotedParse parseUnqtList+ `onFail`+ do cs <- getColorScheme+ failBad $ "Error parsing list of Colors with color scheme of "+ ++ show cs -- ----------------------------------------------------------------------------- @@ -175,6 +185,7 @@ printNC :: Bool -> nc -> DotCode + -- | Bool is for whether quoting is needed. parseNC' :: Bool -> Parse nc -- First value just used for type@@ -234,7 +245,7 @@ => (ColorScheme -> Maybe cs) -> Parse cs -> (cs -> Bool) -> (cs -> lv -> nc) -> Bool -> Parse nc parseNamedColor gcs parseCS vcs mkC q- = do Just cs <- gcs `fmap` getColorScheme+ = do Just cs <- gcs <$> getColorScheme lv <- bool parseUnqt parse q `onFail` mQts (string "//" *> parseUnqt)@@ -244,8 +255,7 @@ cs <- parseCS character '/' if vcs cs- then do lv <- parseUnqt- return $ mkC cs lv+ then mkC cs <$> parseUnqt else fail "Explicit colorscheme not as expected." ) where@@ -256,16 +266,16 @@ -- X11 has a special case when parsing: '/yyyy' parseX11Color :: Bool -> Parse Color-parseX11Color q = fmap X11Color- $ parseNC' q- `onFail`- bool id quotedParse q (character '/' *> parseUnqt)- `onFail`- -- Can use X11 colors within brewer colorscheme.- do cs <- getColorScheme- case cs of- Brewer{} -> bool parseUnqt parse q- _ -> fail "Unable to parse an X11 color within Brewer"+parseX11Color q = X11Color+ <$> parseNC' q+ `onFail`+ bool id quotedParse q (character '/' *> parseUnqt)+ `onFail`+ -- Can use X11 colors within brewer colorscheme.+ do cs <- getColorScheme+ case cs of+ Brewer{} -> bool parseUnqt parse q+ _ -> fail "Unable to parse an X11 color within Brewer" -- -----------------------------------------------------------------------------
Data/GraphViz/Attributes/Complete.hs view
@@ -110,6 +110,7 @@ , Label(..) , VerticalPlacement(..) , LabelScheme(..)+ , SVGFontNames(..) -- *** Types representing the Dot grammar for records. , RecordFields , RecordField(..)@@ -146,6 +147,7 @@ , DPoint(..) -- ** Layout+ , GraphSize(..) , AspectType(..) , ClusterMode(..) , Model(..)@@ -197,7 +199,6 @@ import qualified Data.Set as S import qualified Data.Text.Lazy as T import Data.Text.Lazy(Text)-import Control.Monad(liftM, liftM2) import System.FilePath(searchPathSeparator, splitSearchPath) -- -----------------------------------------------------------------------------@@ -244,9 +245,9 @@ = Damping Double -- ^ /Valid for/: G; /Default/: @0.99@; /Minimum/: @0.0@; /Notes/: neato only | K Double -- ^ /Valid for/: GC; /Default/: @0.3@; /Minimum/: @0@; /Notes/: sfdp, fdp only | URL EscString -- ^ /Valid for/: ENGC; /Default/: none; /Notes/: svg, postscript, map only- | ArrowHead ArrowType -- ^ /Valid for/: E; /Default/: @'AType' [('noMods', 'Normal')]@+ | ArrowHead ArrowType -- ^ /Valid for/: E; /Default/: @'normal'@ | ArrowSize Double -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0.0@- | ArrowTail ArrowType -- ^ /Valid for/: E; /Default/: @'AType' [('noMods', 'Normal')]@+ | ArrowTail ArrowType -- ^ /Valid for/: E; /Default/: @'normal'@ | Aspect AspectType -- ^ /Valid for/: G; /Notes/: dot only | BoundingBox Rect -- ^ /Valid for/: G; /Notes/: write only | ColorScheme ColorScheme -- ^ /Valid for/: ENCG; /Default/: @'X11'@@@ -259,7 +260,7 @@ | 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, only if @'Pack' 'DontPack'@+ | DefaultDist Double -- ^ /Valid for/: G; /Default/: @1+(avg. len)*sqrt(abs(V))@; /Minimum/: @epsilon@; /Notes/: neato only, only if @'Pack' 'DontPack'@ | Dim Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: sfdp, fdp, neato only | Dimen Int -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: sfdp, fdp, neato only | Dir DirType -- ^ /Valid for/: E; /Default/: @'Forward'@ (directed), @'NoDir'@ (undirected)@@ -275,7 +276,7 @@ | FixedSize Bool -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True' | FontColor Color -- ^ /Valid for/: ENGC; /Default/: @'X11Color' 'Black'@ | FontName Text -- ^ /Valid for/: ENGC; /Default/: @\"Times-Roman\"@- | FontNames Text -- ^ /Valid for/: G; /Default/: @\"\"@; /Notes/: svg only+ | FontNames SVGFontNames -- ^ /Valid for/: G; /Default/: @'SvgNames'@; /Notes/: svg only | FontPath Text -- ^ /Valid for/: G; /Default/: system dependent | FontSize Double -- ^ /Valid for/: ENGC; /Default/: @14.0@; /Minimum/: @1.0@ | ForceLabels Bool -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: Only for 'XLabel' attributes, requires Graphviz >= 2.29.0@@ -369,7 +370,7 @@ | ShapeFile Text -- ^ /Valid for/: N; /Default/: @\"\"@ | ShowBoxes Int -- ^ /Valid for/: ENG; /Default/: @0@; /Minimum/: @0@; /Notes/: dot only | Sides Int -- ^ /Valid for/: N; /Default/: @4@; /Minimum/: @0@- | Size Point -- ^ /Valid for/: G+ | Size GraphSize -- ^ /Valid for/: G | Skew Double -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@ | Smoothing SmoothType -- ^ /Valid for/: G; /Default/: @'NoSmooth'@; /Notes/: sfdp only | SortV Word16 -- ^ /Valid for/: GCN; /Default/: @0@; /Minimum/: @0@@@ -559,11 +560,11 @@ listToDot = unqtListToDot instance ParseDot Attribute where- parseUnqt = stringParse (concat [ parseField Damping "Damping"- , parseField K "K"+ parseUnqt = stringParse (concat [ parseFieldNumDef Damping 0.99 "Damping"+ , parseFieldNumDef K 0.3 "K" , parseFields URL ["URL", "href"] , parseField ArrowHead "arrowhead"- , parseField ArrowSize "arrowsize"+ , parseFieldNumDef ArrowSize 1 "arrowsize" , parseField ArrowTail "arrowtail" , parseField Aspect "aspect" , parseField BoundingBox "bb"@@ -578,11 +579,11 @@ , parseFieldBool Constraint "constraint" , parseFieldBool Decorate "decorate" , parseField DefaultDist "defaultdist"- , parseField Dim "dim"- , parseField Dimen "dimen"+ , parseFieldNumDef Dim 2 "dim"+ , parseFieldNumDef Dimen 2 "dimen" , parseField Dir "dir" , parseFieldDef DirEdgeConstraints EdgeConstraints "diredgeconstraints"- , parseField Distortion "distortion"+ , parseFieldNumDef Distortion 0 "distortion" , parseFields DPI ["dpi", "resolution"] , parseFields EdgeURL ["edgeURL", "edgehref"] , parseField EdgeTarget "edgetarget"@@ -595,9 +596,9 @@ , parseField FontName "fontname" , parseField FontNames "fontnames" , parseField FontPath "fontpath"- , parseField FontSize "fontsize"+ , parseFieldNumDef FontSize 14 "fontsize" , parseFieldBool ForceLabels "forcelabels"- , parseField GradientAngle "gradientangle"+ , parseFieldNumDef GradientAngle 0 "gradientangle" , parseField Group "group" , parseFields HeadURL ["headURL", "headhref"] , parseFieldBool HeadClip "headclip"@@ -605,7 +606,7 @@ , parseField HeadPort "headport" , parseField HeadTarget "headtarget" , parseField HeadTooltip "headtooltip"- , parseField Height "height"+ , parseFieldNumDef Height 0.5 "height" , parseField ID "id" , parseField Image "image" , parseField ImagePath "imagepath"@@ -613,12 +614,12 @@ , parseField Label "label" , parseFields LabelURL ["labelURL", "labelhref"] , parseField LabelScheme "label_scheme"- , parseField LabelAngle "labelangle"- , parseField LabelDistance "labeldistance"+ , parseFieldNumDef LabelAngle (-25) "labelangle"+ , parseFieldNumDef LabelDistance 1 "labeldistance" , parseFieldBool LabelFloat "labelfloat" , parseField LabelFontColor "labelfontcolor" , parseField LabelFontName "labelfontname"- , parseField LabelFontSize "labelfontsize"+ , parseFieldNumDef LabelFontSize 14 "labelfontsize" , parseField LabelJust "labeljust" , parseField LabelLoc "labelloc" , parseField LabelTarget "labeltarget"@@ -629,8 +630,8 @@ , parseField LayerSep "layersep" , parseField Layout "layout" , parseField Len "len"- , parseField LevelsGap "levelsgap"- , parseField Levels "levels"+ , parseFieldNumDef LevelsGap 0 "levelsgap"+ , parseFieldNumDef Levels maxBound "levels" , parseField LHead "lhead" , parseField LHeight "LHeight" , parseField LPos "lp"@@ -638,34 +639,34 @@ , parseField LWidth "lwidth" , parseField Margin "margin" , parseField MaxIter "maxiter"- , parseField MCLimit "mclimit"- , parseField MinDist "mindist"- , parseField MinLen "minlen"+ , parseFieldNumDef MCLimit 1 "mclimit"+ , parseFieldNumDef MinDist 1 "mindist"+ , parseFieldNumDef MinLen 1 "minlen" , parseField Mode "mode" , parseField Model "model" , parseFieldBool Mosek "mosek"- , parseField NodeSep "nodesep"+ , parseFieldNumDef NodeSep 0.25 "nodesep" , parseFieldBool NoJustify "nojustify" , parseFieldBool Normalize "normalize" , parseField Nslimit "nslimit" , parseField Nslimit1 "nslimit1" , parseField Ordering "ordering"- , parseField Orientation "orientation"+ , parseFieldNumDef Orientation 0 "orientation" , parseField OutputOrder "outputorder" , parseFieldDef Overlap KeepOverlaps "overlap"- , parseField OverlapScaling "overlap_scaling"+ , parseFieldNumDef OverlapScaling (-4) "overlap_scaling" , parseFieldDef Pack DoPack "pack" , parseField PackMode "packmode" , parseField Pad "pad" , parseField Page "page" , parseField PageDir "pagedir" , parseField PenColor "pencolor"- , parseField PenWidth "penwidth"- , parseField Peripheries "peripheries"+ , parseFieldNumDef PenWidth 1 "penwidth"+ , parseFieldNumDef Peripheries 1 "peripheries" , parseFieldBool Pin "pin" , parseField Pos "pos" , parseFieldDef QuadTree NormalQT "quadtree"- , parseField Quantum "quantum"+ , parseFieldNumDef Quantum 0 "quantum" , parseField Rank "rank" , parseField RankDir "rankdir" , parseField RankSep "ranksep"@@ -673,22 +674,22 @@ , parseField Rects "rects" , parseFieldBool Regular "regular" , parseFieldBool ReMinCross "remincross"- , parseField RepulsiveForce "repulsiveforce"+ , parseFieldNumDef RepulsiveForce 1 "repulsiveforce" , parseFieldDef Root IsCentral "root"- , parseField Rotate "rotate"- , parseField Rotation "rotation"+ , parseFieldNumDef Rotate 0 "rotate"+ , parseFieldNumDef Rotation 0 "rotation" , parseField SameHead "samehead" , parseField SameTail "sametail" , parseField SamplePoints "samplepoints" , parseField Scale "scale"- , parseField SearchSize "searchsize"+ , parseFieldNumDef SearchSize 30 "searchsize" , parseField Sep "sep" , parseField Shape "shape" , parseField ShapeFile "shapefile"- , parseField ShowBoxes "showboxes"- , parseField Sides "sides"+ , parseFieldNumDef ShowBoxes 0 "showboxes"+ , parseFieldNumDef Sides 4 "sides" , parseField Size "size"- , parseField Skew "skew"+ , parseFieldNumDef Skew 0 "skew" , parseField Smoothing "smoothing" , parseField SortV "sortv" , parseFieldDef Splines SplineEdges "splines"@@ -706,14 +707,16 @@ , parseFieldBool TrueColor "truecolor" , parseField Vertices "vertices" , parseField ViewPort "viewport"- , parseField VoroMargin "voro_margin"+ , parseFieldNumDef VoroMargin 0.05 "voro_margin" , parseField Weight "weight"- , parseField Width "width"+ , parseFieldNumDef Width 0.75 "width" , parseField XLabel "xlabel"- , parseField Z "z"+ , parseFieldNumDef Z 0 "z" ]) `onFail`- liftM2 UnknownAttribute stringBlock (parseEq >> parse)+ do attrName <- stringBlock+ liftEqParse' ("UnknownAttribute (" ++ T.unpack attrName ++ ")")+ (UnknownAttribute attrName) parse = parseUnqt @@ -1142,7 +1145,7 @@ defaultAttributeValue FixedSize{} = Just $ FixedSize False defaultAttributeValue FontColor{} = Just $ FontColor (X11Color Black) defaultAttributeValue FontName{} = Just $ FontName "Times-Roman"-defaultAttributeValue FontNames{} = Just $ FontNames ""+defaultAttributeValue FontNames{} = Just $ FontNames SvgNames defaultAttributeValue FontSize{} = Just $ FontSize 14 defaultAttributeValue ForceLabels{} = Just $ ForceLabels False defaultAttributeValue GradientAngle{} = Just $ GradientAngle 0@@ -1545,10 +1548,7 @@ instance ParseDot ArrowType where parseUnqt = specialArrowParse `onFail`- do mas <- many1 $ do m <- parseUnqt- a <- parseUnqt- return (m,a)- return $ AType mas+ (AType <$> many1 (liftA2 (,) parseUnqt parseUnqt)) specialArrowParse :: Parse ArrowType specialArrowParse = stringValue [ ("ediamond", eDiamond)@@ -1610,9 +1610,7 @@ unqtDot (ArrMod f s) = unqtDot f <> unqtDot s instance ParseDot ArrowModifier where- parseUnqt = do f <- parseUnqt- s <- parseUnqt- return $ ArrMod f s+ parseUnqt = liftA2 ArrMod parseUnqt parseUnqt data ArrowFill = OpenArrow | FilledArrow@@ -1623,8 +1621,7 @@ unqtDot FilledArrow = empty instance ParseDot ArrowFill where- parseUnqt = liftM (bool FilledArrow OpenArrow . isJust)- $ optional (character 'o')+ parseUnqt = bool FilledArrow OpenArrow . isJust <$> optional (character 'o') -- Not used individually parse = parseUnqt@@ -1642,8 +1639,7 @@ unqtDot BothSides = empty instance ParseDot ArrowSide where- parseUnqt = liftM getSideType- $ optional (oneOf $ map character ['l', 'r'])+ parseUnqt = getSideType <$> optional (oneOf $ map character ['l', 'r']) where getSideType = maybe BothSides (bool RightSide LeftSide . (==) 'l')@@ -1665,14 +1661,14 @@ toDot at@RatioPassCount{} = dquotes $ unqtDot at instance ParseDot AspectType where- parseUnqt = liftM (uncurry RatioPassCount) commaSepUnqt+ parseUnqt = fmap (uncurry RatioPassCount) commaSepUnqt `onFail`- liftM RatioOnly parseUnqt+ fmap RatioOnly parseUnqt - parse = quotedParse (liftM (uncurry RatioPassCount) commaSepUnqt)+ parse = quotedParse (uncurry RatioPassCount <$> commaSepUnqt) `onFail`- liftM RatioOnly parse+ fmap RatioOnly parse -- ----------------------------------------------------------------------------- @@ -1681,14 +1677,14 @@ deriving (Eq, Ord, Show, Read) instance PrintDot Rect where- unqtDot (Rect p1 p2) = commaDel p1 p2+ unqtDot (Rect p1 p2) = printPoint2DUnqt p1 <> comma <> printPoint2DUnqt p2 toDot = dquotes . unqtDot unqtListToDot = hsep . mapM unqtDot instance ParseDot Rect where- parseUnqt = liftM (uncurry Rect) $ commaSep' parsePoint2D parsePoint2D+ parseUnqt = uncurry Rect <$> commaSep' parsePoint2D parsePoint2D parse = quotedParse parseUnqt @@ -1750,7 +1746,7 @@ unqtDot HierConstraints = text "hier" instance ParseDot DEConstraints where- parseUnqt = liftM (bool NoConstraints EdgeConstraints) parse+ parseUnqt = fmap (bool NoConstraints EdgeConstraints) parse `onFail` stringRep HierConstraints "hier" @@ -1758,28 +1754,90 @@ -- | Either a 'Double' or a (2D) 'Point' (i.e. created with -- 'createPoint').+--+-- Whilst it is possible to create a 'Point' value with either a+-- third co-ordinate or a forced position, these are ignored for+-- printing/parsing.+--+-- An optional prefix of @\'+\'@ is allowed when parsing. data DPoint = DVal Double | PVal Point deriving (Eq, Ord, Show, Read) instance PrintDot DPoint where unqtDot (DVal d) = unqtDot d- unqtDot (PVal p) = unqtDot p+ unqtDot (PVal p) = printPoint2DUnqt p toDot (DVal d) = toDot d- toDot (PVal p) = toDot p+ toDot (PVal p) = printPoint2D p instance ParseDot DPoint where- parseUnqt = liftM PVal parsePoint2D+ parseUnqt = fmap PVal parsePoint2D `onFail`- liftM DVal parseUnqt+ fmap DVal parseUnqt parse = quotedParse parseUnqt `onFail`- liftM DVal parseUnqt+ fmap DVal parseUnqt -- ----------------------------------------------------------------------------- +-- | The mapping used for 'FontName' values in SVG output.+--+-- More information can be found at <http://www.graphviz.org/doc/fontfaq.txt>.+data SVGFontNames = SvgNames -- ^ Use the legal generic SVG font names.+ | PostScriptNames -- ^ Use PostScript font names.+ | FontConfigNames -- ^ Use fontconfig font conventions.+ deriving (Eq, Ord, Bounded, Enum, Show, Read)++instance PrintDot SVGFontNames where+ unqtDot SvgNames = text "svg"+ unqtDot PostScriptNames = text "ps"+ unqtDot FontConfigNames = text "gd"++instance ParseDot SVGFontNames where+ parseUnqt = oneOf [ stringRep SvgNames "svg"+ , stringRep PostScriptNames "ps"+ , stringRep FontConfigNames "gd"+ ]++ parse = stringRep SvgNames "\"\""+ `onFail`+ optionalQuoted parseUnqt++-- -----------------------------------------------------------------------------++-- | Maximum width and height of drawing in inches.+data GraphSize = GSize { width :: Double+ -- | If @Nothing@, then the height is the+ -- same as the width.+ , height :: Maybe Double+ -- | If drawing is smaller than specified+ -- size, this value determines whether it+ -- is scaled up.+ , desiredSize :: Bool+ }+ deriving (Eq, Ord, Show, Read)++instance PrintDot GraphSize where+ unqtDot (GSize w mh ds) = bool id (<> char '!') ds+ . maybe id (\h -> (<> unqtDot h) . (<> comma)) mh+ $ unqtDot w++ toDot (GSize w Nothing False) = toDot w+ toDot gs = dquotes $ unqtDot gs++instance ParseDot GraphSize where+ parseUnqt = GSize <$> parseUnqt+ <*> optional (parseComma *> whitespace *> parseUnqt)+ <*> (isJust <$> optional (character '!'))++ parse = quotedParse parseUnqt+ `onFail`+ fmap (\ w -> GSize w Nothing False) parseUnqt++-- -----------------------------------------------------------------------------+ data ModeType = Major | KK | Hier@@ -1845,14 +1903,14 @@ -- between an HtmlLabel and a RecordLabel starting with a PortPos, -- since the latter will be in quotes and the former won't. - parseUnqt = oneOf [ liftM HtmlLabel $ parseAngled parseUnqt- , liftM RecordLabel parseUnqt- , liftM StrLabel parseUnqt+ parseUnqt = oneOf [ HtmlLabel <$> parseAngled parseUnqt+ , RecordLabel <$> parseUnqt+ , StrLabel <$> parseUnqt ] - parse = oneOf [ liftM HtmlLabel $ parseAngled parse- , liftM RecordLabel parse- , liftM StrLabel parse+ parse = oneOf [ HtmlLabel <$> parseAngled parse+ , RecordLabel <$> parse+ , StrLabel <$> parse ] -- -----------------------------------------------------------------------------@@ -1888,15 +1946,16 @@ listToDot fs = dquotes $ unqtListToDot fs instance ParseDot RecordField where- parseUnqt = do t <- liftM PN $ parseAngled parseRecord- ml <- optional (whitespace1 >> parseRecord)- return $ maybe (PortName t)- (LabelledTarget t)- ml+ parseUnqt = (liftA2 maybe PortName LabelledTarget+ <$> (PN <$> parseAngled parseRecord)+ <*> optional (whitespace1 *> parseRecord)+ ) `onFail`- liftM FieldLabel parseRecord+ fmap FieldLabel parseRecord `onFail`- liftM FlipFields (parseBraced parseUnqt)+ fmap FlipFields (parseBraced parseUnqt)+ `onFail`+ fail "Unable to parse RecordField" parse = quotedParse parseUnqt @@ -1966,8 +2025,14 @@ 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 = liftM (uncurry createPoint) commaSepUnqt+parsePoint2D = uncurry createPoint <$> commaSepUnqt instance PrintDot Point where unqtDot (Point x y mz frs) = bool id (<> char '!') frs@@ -1981,10 +2046,10 @@ listToDot = dquotes . unqtListToDot instance ParseDot Point where- parseUnqt = do (x,y) <- commaSepUnqt- mz <- optional $ parseComma >> parseUnqt- bng <- liftM isJust . optional $ character '!'- return $ Point x y mz bng+ parseUnqt = uncurry Point+ <$> commaSepUnqt+ <*> optional (parseComma *> parseUnqt)+ <*> (isJust <$> optional (character '!')) parse = quotedParse parseUnqt @@ -2017,7 +2082,7 @@ parseUnqt = oneOf [ stringRep KeepOverlaps "true" , stringRep ScaleXYOverlaps "scalexy" , stringRep ScaleOverlaps "scale"- , string "prism" >> liftM PrismOverlap (optional parse)+ , string "prism" *> fmap PrismOverlap (optional parse) , stringRep (PrismOverlap Nothing) "false" , stringRep CompressOverlap "compress" , stringRep VpscOverlap "vpsc"@@ -2030,11 +2095,9 @@ deriving (Eq, Ord, Show, Read) instance PrintDot LayerSep where- unqtDot (LSep ls) = do setLayerSep $ T.unpack ls- unqtDot ls+ unqtDot (LSep ls) = setLayerSep (T.unpack ls) *> unqtDot ls - toDot (LSep ls) = do setLayerSep $ T.unpack ls- toDot ls+ toDot (LSep ls) = setLayerSep (T.unpack ls) *> toDot ls instance ParseDot LayerSep where parseUnqt = do ls <- parseUnqt@@ -2059,26 +2122,18 @@ toDot lrs = dquotes $ unqtDot lrs instance ParseDot LayerRange where- parseUnqt = do id1 <- parseUnqt- _ <- parseLayerSep- id2 <- parseUnqt- return $ LRS id1 id2+ parseUnqt = ignoreSep LRS parseUnqt parseLayerSep parseUnqt `onFail`- liftM LRID parseUnqt+ fmap LRID parseUnqt - parse = quotedParse ( do id1 <- parseUnqt- _ <- parseLayerSep- id2 <- parseUnqt- return $ LRS id1 id2- )+ parse = quotedParse (ignoreSep LRS parseUnqt parseLayerSep parseUnqt) `onFail`- liftM LRID parse+ fmap LRID parse parseLayerSep :: Parse () parseLayerSep = do ls <- getLayerSep- many1Satisfy (`elem` ls)- return ()+ many1Satisfy (`elem` ls) *> return () parseLayerName :: Parse Text parseLayerName = parseEscaped False [] =<< getLayerSep@@ -2114,10 +2169,10 @@ listToDot ll = dquotes $ unqtDot ll instance ParseDot LayerID where- parseUnqt = liftM checkLayerName parseLayerName -- tests for Int and All+ parseUnqt = checkLayerName <$> parseLayerName -- tests for Int and All - parse = oneOf [ liftM checkLayerName parseLayerName'- , liftM LRInt parse -- Mainly for unquoted case.+ parse = oneOf [ checkLayerName <$> parseLayerName'+ , LRInt <$> parse -- Mainly for unquoted case. ] checkLayerName :: Text -> LayerID@@ -2139,11 +2194,11 @@ toDot (LL ll) = toDot ll instance ParseDot LayerList where- parseUnqt = liftM LL $ sepBy1 parseUnqt parseLayerSep+ parseUnqt = LL <$> sepBy1 parseUnqt parseLayerSep parse = quotedParse parseUnqt `onFail`- liftM (LL . (:[]) . LRName) stringBlock+ fmap (LL . (:[]) . LRName) stringBlock `onFail` quotedParse (stringRep (LL []) "") @@ -2192,8 +2247,8 @@ instance ParseDot Pack where -- What happens if it parses 0? It's non-negative, but parses as False- parseUnqt = oneOf [ liftM PackMargin parseUnqt- , liftM (bool DontPack DoPack) onlyBool+ parseUnqt = oneOf [ PackMargin <$> parseUnqt+ , bool DontPack DoPack <$> onlyBool ] -- -----------------------------------------------------------------------------@@ -2229,8 +2284,7 @@ , stringRep PackClust "clust" , stringRep PackGraph "graph" , do string "array"- mcu <- optional $ do character '_'- many1 $ satisfy isCU+ mcu <- optional $ character '_' *> many1 (satisfy isCU) let c = hasCharacter mcu 'c' u = hasCharacter mcu 'u' mi <- optional parseUnqt@@ -2288,7 +2342,7 @@ instance ParseDot EdgeType where -- Can't parse NoEdges without quotes.- parseUnqt = oneOf [ liftM (bool LineEdges SplineEdges) parse+ parseUnqt = oneOf [ bool LineEdges SplineEdges <$> parse , stringRep SplineEdges "spline" , stringRep LineEdges "line" , stringRep PolyLine "polyline"@@ -2331,11 +2385,14 @@ -- | 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]+data Spline = Spline { endPoint :: Maybe Point+ , startPoint :: Maybe Point+ , splinePoints :: [Point]+ } deriving (Eq, Ord, Show, Read) instance PrintDot Spline where- unqtDot (Spline ms me ps) = addS . addE+ unqtDot (Spline me ms ps) = addE . addS . hsep $ mapM unqtDot ps where@@ -2350,14 +2407,10 @@ listToDot = dquotes . unqtListToDot instance ParseDot Spline where- parseUnqt = do ms <- parseP 's'- me <- parseP 'e'- ps <- sepBy1 parseUnqt whitespace1- return $ Spline ms me ps+ parseUnqt = Spline <$> parseP 'e' <*> parseP 's'+ <*> sepBy1 parseUnqt whitespace1 where- parseP t = optional $ do character t- parseComma- parseUnqt `discard` whitespace1+ parseP t = optional (character t *> parseComma *> parseUnqt <* whitespace1) parse = quotedParse parseUnqt @@ -2381,8 +2434,8 @@ parseUnqt = oneOf [ stringRep NormalQT "normal" , stringRep FastQT "fast" , stringRep NoQT "none"- , character '2' >> return FastQT -- weird bool- , liftM (bool NoQT NormalQT) parse+ , character '2' *> return FastQT -- weird bool+ , bool NoQT NormalQT <$> parse ] -- -----------------------------------------------------------------------------@@ -2402,13 +2455,13 @@ toDot r = unqtDot r instance ParseDot Root where- parseUnqt = liftM (bool NotCentral IsCentral) onlyBool+ parseUnqt = fmap (bool NotCentral IsCentral) onlyBool `onFail`- liftM NodeName parseUnqt+ fmap NodeName parseUnqt - parse = optionalQuoted (liftM (bool NotCentral IsCentral) onlyBool)+ parse = optionalQuoted (bool NotCentral IsCentral <$> onlyBool) `onFail`- liftM NodeName parse+ fmap NodeName parse -- ----------------------------------------------------------------------------- @@ -2460,7 +2513,7 @@ data Shape = BoxShape -- ^ Has synonyms of /rect/ and /rectangle/. | Polygon- | Ellipse+ | Ellipse -- ^ Has synonym of /oval/. | Circle | PointShape | Egg@@ -2488,43 +2541,83 @@ | Folder | Box3D | Component+ | Promoter+ | CDS+ | Terminator+ | UTR+ | PrimerSite+ | RestrictionSite+ | FivePovOverhang+ | ThreePovOverhang+ | NoOverhang+ | Assembly+ | Signature+ | Insulator+ | Ribosite+ | RNAStab+ | ProteaseSite+ | ProteinStab+ | RPromoter+ | RArrow+ | LArrow+ | LPromoter | Record -- ^ Must specify the record shape with a 'Label'. | MRecord -- ^ Must specify the record shape with a 'Label'. deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot Shape where- unqtDot BoxShape = text "box"- unqtDot Polygon = text "polygon"- unqtDot Ellipse = text "ellipse"- unqtDot Circle = text "circle"- unqtDot PointShape = text "point"- unqtDot Egg = text "egg"- unqtDot Triangle = text "triangle"- unqtDot PlainText = text "plaintext"- unqtDot DiamondShape = text "diamond"- unqtDot Trapezium = text "trapezium"- unqtDot Parallelogram = text "parallelogram"- unqtDot House = text "house"- unqtDot Pentagon = text "pentagon"- unqtDot Hexagon = text "hexagon"- unqtDot Septagon = text "septagon"- unqtDot Octagon = text "octagon"- unqtDot DoubleCircle = text "doublecircle"- unqtDot DoubleOctagon = text "doubleoctagon"- unqtDot TripleOctagon = text "tripleoctagon"- unqtDot InvTriangle = text "invtriangle"- unqtDot InvTrapezium = text "invtrapezium"- unqtDot InvHouse = text "invhouse"- unqtDot MDiamond = text "Mdiamond"- unqtDot MSquare = text "Msquare"- unqtDot MCircle = text "Mcircle"- unqtDot Note = text "note"- unqtDot Tab = text "tab"- unqtDot Folder = text "folder"- unqtDot Box3D = text "box3d"- unqtDot Component = text "component"- unqtDot Record = text "record"- unqtDot MRecord = text "Mrecord"+ unqtDot BoxShape = text "box"+ unqtDot Polygon = text "polygon"+ unqtDot Ellipse = text "ellipse"+ unqtDot Circle = text "circle"+ unqtDot PointShape = text "point"+ unqtDot Egg = text "egg"+ unqtDot Triangle = text "triangle"+ unqtDot PlainText = text "plaintext"+ unqtDot DiamondShape = text "diamond"+ unqtDot Trapezium = text "trapezium"+ unqtDot Parallelogram = text "parallelogram"+ unqtDot House = text "house"+ unqtDot Pentagon = text "pentagon"+ unqtDot Hexagon = text "hexagon"+ unqtDot Septagon = text "septagon"+ unqtDot Octagon = text "octagon"+ unqtDot DoubleCircle = text "doublecircle"+ unqtDot DoubleOctagon = text "doubleoctagon"+ unqtDot TripleOctagon = text "tripleoctagon"+ unqtDot InvTriangle = text "invtriangle"+ unqtDot InvTrapezium = text "invtrapezium"+ unqtDot InvHouse = text "invhouse"+ unqtDot MDiamond = text "Mdiamond"+ unqtDot MSquare = text "Msquare"+ unqtDot MCircle = text "Mcircle"+ unqtDot Note = text "note"+ unqtDot Tab = text "tab"+ unqtDot Folder = text "folder"+ unqtDot Box3D = text "box3d"+ unqtDot Component = text "component"+ unqtDot Promoter = text "promoter"+ unqtDot CDS = text "cds"+ unqtDot Terminator = text "terminator"+ unqtDot UTR = text "utr"+ unqtDot PrimerSite = text "primersite"+ unqtDot RestrictionSite = text "restrictionsite"+ unqtDot FivePovOverhang = text "fivepovoverhang"+ unqtDot ThreePovOverhang = text "threepovoverhang"+ unqtDot NoOverhang = text "nooverhang"+ unqtDot Assembly = text "assembly"+ unqtDot Signature = text "signature"+ unqtDot Insulator = text "insulator"+ unqtDot Ribosite = text "ribosite"+ unqtDot RNAStab = text "rnastab"+ unqtDot ProteaseSite = text "proteasesite"+ unqtDot ProteinStab = text "proteinstab"+ unqtDot RPromoter = text "rpromoter"+ unqtDot RArrow = text "rarrow"+ unqtDot LArrow = text "larrow"+ unqtDot LPromoter = text "lpromoter"+ unqtDot Record = text "record"+ unqtDot MRecord = text "Mrecord" instance ParseDot Shape where parseUnqt = stringValue [ ("box3d", Box3D)@@ -2533,6 +2626,7 @@ , ("rect", BoxShape) , ("polygon", Polygon) , ("ellipse", Ellipse)+ , ("oval", Ellipse) , ("circle", Circle) , ("point", PointShape) , ("egg", Egg)@@ -2560,6 +2654,26 @@ , ("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) ]@@ -2607,11 +2721,9 @@ unqtDot (StartStyleSeed ss s) = unqtDot ss <> unqtDot s instance ParseDot StartType where- parseUnqt = oneOf [ do ss <- parseUnqt- s <- parseUnqt- return $ StartStyleSeed ss s- , liftM StartStyle parseUnqt- , liftM StartSeed parseUnqt+ parseUnqt = oneOf [ liftA2 StartStyleSeed parseUnqt parseUnqt+ , StartStyle <$> parseUnqt+ , StartSeed <$> parseUnqt ] data STStyle = RegularStyle@@ -2655,20 +2767,18 @@ listToDot sis = dquotes $ unqtListToDot sis instance ParseDot StyleItem where- parseUnqt = do nm <- parseUnqt- args <- tryParseList' parseArgs- return $ SItem nm args+ parseUnqt = liftA2 SItem parseUnqt (tryParseList' parseArgs) - parse = quotedParse (liftM2 SItem parseUnqt parseArgs)+ parse = quotedParse (liftA2 SItem parseUnqt parseArgs) `onFail`- liftM (flip SItem []) parse+ fmap (flip SItem []) parse parseUnqtList = sepBy1 parseUnqt parseComma parseList = quotedParse parseUnqtList `onFail` -- Might not necessarily need to be quoted if a singleton...- liftM return parse+ fmap return parse parseArgs :: Parse [Text] parseArgs = bracketSep (character '(')@@ -2709,11 +2819,11 @@ toDot sn = unqtDot sn instance ParseDot StyleName where- parseUnqt = liftM checkDD parseStyleName+ parseUnqt = checkDD <$> parseStyleName parse = quotedParse parseUnqt `onFail`- liftM checkDD quotelessString+ fmap checkDD quotelessString checkDD :: Text -> StyleName checkDD str = case T.toLower str of@@ -2730,9 +2840,8 @@ _ -> DD str parseStyleName :: Parse Text-parseStyleName = do f <- orEscaped . noneOf $ ' ' : disallowedChars- r <- parseEscaped True [] disallowedChars- return $ f `T.cons` r+parseStyleName = liftA2 T.cons (orEscaped . noneOf $ ' ' : disallowedChars)+ (parseEscaped True [] disallowedChars) where disallowedChars = [quoteChar, '(', ')', ','] -- Used because the first character has slightly stricter requirements than the rest.@@ -2758,13 +2867,12 @@ toDot = dquotes . unqtDot instance ParseDot ViewPort where- parseUnqt = do wv <- parseUnqt- parseComma- hv <- parseUnqt- parseComma- zv <- parseUnqt- mf <- optional $ parseComma >> parseUnqt- return $ VP wv hv zv mf+ parseUnqt = VP <$> parseUnqt+ <* parseComma+ <*> parseUnqt+ <* parseComma+ <*> parseUnqt+ <*> optional (parseComma *> parseUnqt) parse = quotedParse parseUnqt @@ -2781,13 +2889,13 @@ toDot (NodeFocus nm) = toDot nm instance ParseDot FocusType where- parseUnqt = liftM XY parseUnqt+ parseUnqt = fmap XY parseUnqt `onFail`- liftM NodeFocus parseUnqt+ fmap NodeFocus parseUnqt - parse = liftM XY parse+ parse = fmap XY parse `onFail`- liftM NodeFocus parse+ fmap NodeFocus parse -- ----------------------------------------------------------------------------- @@ -2819,11 +2927,11 @@ toDot ps = dquotes $ unqtDot ps instance ParseDot Paths where- parseUnqt = liftM (Paths . splitSearchPath) parseUnqt+ parseUnqt = Paths . splitSearchPath <$> parseUnqt parse = quotedParse parseUnqt `onFail`- liftM (Paths . (:[]) . T.unpack) quotelessString+ fmap (Paths . (:[]) . T.unpack) quotelessString -- ----------------------------------------------------------------------------- @@ -2884,7 +2992,7 @@ unqtDot AutoRatio = text "auto" instance ParseDot Ratios where- parseUnqt = oneOf [ liftM AspectRatio parseUnqt+ parseUnqt = oneOf [ AspectRatio <$> parseUnqt , stringRep FillRatio "fill" , stringRep CompressRatio "compress" , stringRep ExpandRatio "expand"
Data/GraphViz/Attributes/HTML.hs view
@@ -81,7 +81,6 @@ import Data.Word(Word8, Word16) import qualified Data.Map as Map import qualified Data.Text.Lazy as T-import Control.Monad(liftM, liftM2) -- ----------------------------------------------------------------------------- @@ -99,9 +98,9 @@ instance ParseDot Label where -- Try parsing Table first in case of a FONT tag being used.- parseUnqt = liftM Table parseUnqt+ parseUnqt = fmap Table parseUnqt `onFail`- liftM Text parseUnqt+ fmap Text parseUnqt `adjustErr` ("Can't parse Html.Label\n\t"++) @@ -140,7 +139,7 @@ listToDot = unqtListToDot instance ParseDot TextItem where- parseUnqt = oneOf [ liftM Str unescapeValue+ parseUnqt = oneOf [ fmap Str unescapeValue , parseEmptyTag Newline "BR" , parseFontTag Font parseUnqt , parseTagRep Format parseUnqt parseUnqt@@ -150,7 +149,7 @@ parse = parseUnqt - parseUnqtList = many1 parseUnqt -- sepBy1 parseUnqt whitespace+ parseUnqtList = many parseUnqt parseList = parseUnqtList @@ -381,7 +380,7 @@ , parseHtmlField' (Port . PN) "PORT" unescapeAttribute , parseHtmlField RowSpan "ROWSPAN" , parseHtmlField Scale "SCALE"- , parseHtmlField' Src "SRC" $ liftM T.unpack unescapeAttribute+ , parseHtmlField' Src "SRC" $ fmap T.unpack unescapeAttribute , parseHtmlField' Target "TARGET" unescapeAttribute , parseHtmlField' Title "TITLE" unescapeAttribute `onFail`@@ -404,9 +403,15 @@ parseHtmlField' :: (a -> Attribute) -> String -> Parse a -> Parse Attribute-parseHtmlField' c f p = do string f- parseEq- liftM c $ quotedParse p+parseHtmlField' c f p = string f+ *> parseEq+ *> ( c <$> ( quotedParse p+ `adjustErr`+ (("Can't parse HTML.Attribute." ++ f ++ "\n\t")++)+ )+ )+-- Can't use liftEqParse, etc. here because it causes backtracking+-- problems when the attributes could apply to multiple constructors. -- | Specifies horizontal placement. When an object is allocated more -- space than required, this value determines where the extra space@@ -460,11 +465,11 @@ -- cell. If undefined, the image inherits the value of the -- @ImageScale@ attribute. data Scale = NaturalSize -- ^ Default value.- | ScaleUniformly- | ExpandWidth- | ExpandHeight- | ExpandBoth- deriving (Eq, Ord, Bounded, Enum, Show, Read)+ | ScaleUniformly+ | ExpandWidth+ | ExpandHeight+ | ExpandBoth+ deriving (Eq, Ord, Bounded, Enum, Show, Read) instance PrintDot Scale where unqtDot NaturalSize = text "FALSE"@@ -492,14 +497,14 @@ escapeValue = escapeHtml True escapeHtml :: Bool -> T.Text -> DotCode-escapeHtml quotesAllowed = hcat . liftM concat+escapeHtml quotesAllowed = hcat . fmap concat . mapM (escapeSegment . T.unpack) . T.groupBy ((==) `on` isSpace) where -- Note: use numeric version of space rather than nbsp, since this -- matches what Graphviz does (since Inkscape apparently can't -- cope with nbsp).- escapeSegment (s:sps) | isSpace s = liftM2 (:) (char s) $ mapM numEscape sps+ escapeSegment (s:sps) | isSpace s = liftA2 (:) (char s) $ mapM numEscape sps escapeSegment txt = mapM xmlChar txt allowQuotes = if quotesAllowed@@ -523,7 +528,7 @@ -- Note: this /will/ fail if an unknown non-numeric HTML-escape is -- used. unescapeHtml :: Bool -> Parse T.Text-unescapeHtml quotesAllowed = liftM (T.pack . catMaybes)+unescapeHtml quotesAllowed = fmap (T.pack . catMaybes) . many1 . oneOf $ [ parseEscpd , validChars ]@@ -551,7 +556,7 @@ escMap = Map.fromList htmlUnescapes - validChars = liftM Just $ satisfy (`notElem` needEscaping)+ validChars = fmap Just $ satisfy (`notElem` needEscaping) needEscaping = allowQuotes $ map fst htmlEscapes -- | The characters that need to be escaped and what they need to be@@ -610,32 +615,38 @@ -- | Parse something like @<FOO ATTR=\"ATTR_VALUE\">value<\/FOO>@ parseTag :: (Attributes -> val -> tag) -> String -> Parse val -> Parse tag-parseTag c t pv = do as <- parseAngled openingTag- v <- pv- parseAngled $ character '/' >> t' >> whitespace- return $ c as v+parseTag c t pv = c <$> parseAngled openingTag+ <*> pv+ <* parseAngled (character '/' *> t' *> whitespace)+ `adjustErr`+ (("Can't parse Html tag: " ++ t ++ "\n\t")++) where t' = string t- openingTag = do t'- as <- tryParseList' $ whitespace1 >> parse- whitespace- return as--parseTagRep :: (tagName -> val -> tag) -> Parse tagName -> Parse val -> Parse tag-parseTagRep c pt pv = do tn <- parseAngled (pt `discard` whitespace)- v <- pv- parseAngled $ character '/' >> pt >> whitespace- return $ c tn v+ openingTag :: Parse Attributes+ openingTag = t'+ *> tryParseList' (whitespace1 >> parse)+ <* whitespace parseFontTag :: (Attributes -> val -> tag) -> Parse val -> Parse tag parseFontTag = flip parseTag "FONT" +-- Should this just be specialised for tagName ~ Format ?++-- | Parse something like @<FOO>value<\/FOO>@.+parseTagRep :: (tagName -> val -> tag) -> Parse tagName -> Parse val -> Parse tag+parseTagRep c pt pv = c <$> parseAngled (pt `discard` whitespace)+ <*> pv+ <* parseAngled (character '/' *> pt *> whitespace)+ `adjustErr`+ ("Can't parse attribute-less Html tag\n\t"++)+ -- | Parse something like @<FOO ATTR=\"ATTR_VALUE\"\/>@ parseEmptyTag :: (Attributes -> tag) -> String -> Parse tag-parseEmptyTag c t = parseAngled- ( do string t- as <- tryParseList' $ whitespace1 >> parse- whitespace- character '/'- return $ c as+parseEmptyTag c t = c <$> parseAngled+ ( string t+ *> tryParseList' (whitespace1 *> parse)+ <* whitespace+ <* character '/' )+ `adjustErr`+ (("Can't parse empty Html tag: " ++ t ++ "\n\t")++)
Data/GraphViz/Attributes/Internal.hs view
@@ -28,7 +28,6 @@ import qualified Data.Map as Map import Data.Map(Map) import Data.Text.Lazy(Text)-import Control.Monad(liftM, liftM2) -- ----------------------------------------------------------------------------- @@ -52,15 +51,14 @@ toDot = toDot . portName instance ParseDot PortName where- parseUnqt = liftM PN- $ parseEscaped False [] ['"', ':']+ parseUnqt = PN <$> parseEscaped False [] ['"', ':'] parse = quotedParse parseUnqt `onFail` unqtPortName unqtPortName :: Parse PortName-unqtPortName = liftM PN quotelessString+unqtPortName = PN <$> quotelessString -- ----------------------------------------------------------------------------- @@ -86,7 +84,7 @@ parse = quotedParse parseUnqt `onFail`- liftM checkPortName unqtPortName+ fmap checkPortName unqtPortName checkPortName :: PortName -> PortPos checkPortName pn = maybe (LabelledPort pn Nothing) CompassPoint@@ -96,7 +94,7 @@ -- | When attached to a node in a DotEdge definition, the 'PortName' -- and the 'CompassPoint' can be in separate quotes. parseEdgeBasedPP :: Parse PortPos-parseEdgeBasedPP = liftM2 LabelledPort parse (liftM Just $ character ':' >> parse)+parseEdgeBasedPP = liftA2 LabelledPort parse (fmap Just $ character ':' *> parse) `onFail` parse
Data/GraphViz/Commands.hs view
@@ -45,9 +45,6 @@ , quitWithoutGraphviz ) where --- Want to use the extensible-exception version-import Prelude hiding (catch)- import Data.GraphViz.Types -- This is here just for Haddock linking purposes. import Data.GraphViz.Attributes.Complete(Attribute(Z))
Data/GraphViz/Parsing.hs view
@@ -33,6 +33,7 @@ , checkValidParse -- * Convenience parsing combinators. , bracket+ , ignoreSep , onlyBool , quotelessString , stringBlock@@ -68,6 +69,9 @@ , parseFieldsBool , parseFieldDef , parseFieldsDef+ , parseFieldNumDef+ , liftEqParse+ , liftEqParse' , commaSep , commaSepUnqt , commaSep'@@ -96,7 +100,7 @@ ) import Data.List(groupBy, sortBy) import Data.Function(on)-import Data.Maybe(fromMaybe, isNothing, listToMaybe)+import Data.Maybe(fromMaybe, isJust, isNothing, listToMaybe) import Data.Ratio((%)) import qualified Data.Set as Set import qualified Data.Text.Lazy as T@@ -104,7 +108,7 @@ import Data.Text.Lazy(Text) import Data.Word(Word8, Word16) import Control.Arrow(first, second)-import Control.Monad(liftM, liftM2, when)+import Control.Monad(when) -- ----------------------------------------------------------------------------- -- Based off code from Text.Parse in the polyparse library@@ -122,7 +126,7 @@ runParser' :: Parse a -> Text -> a runParser' p = checkValidParse . fst . runParser p' where- p' = p `discard` (whitespace >> eof)+ p' = p `discard` (whitespace *> eof) class ParseDot a where parseUnqt :: Parse a@@ -136,7 +140,7 @@ `onFail` whitespace1 )- (whitespace >> character ']')+ (whitespace *> character ']') parseUnqt parseList :: Parse [a]@@ -177,12 +181,12 @@ parseList = quotedParse parseUnqtList `onFail`- liftM return parse+ fmap (:[]) parse instance ParseDot Bool where parseUnqt = onlyBool `onFail`- liftM (zero /=) parseInt'+ fmap (zero /=) parseInt' where zero :: Int zero = 0@@ -201,9 +205,9 @@ `onFail` quotedParse parseUnqt - parseUnqtList = liftM T.unpack parseUnqt+ parseUnqtList = T.unpack <$> parseUnqt - parseList = liftM T.unpack parse+ parseList = T.unpack <$> parse instance ParseDot Text where -- Too many problems with using this within other parsers where@@ -227,34 +231,38 @@ quotelessString = numString `onFail` stringBlock numString :: Parse Text-numString = liftM tShow parseStrictFloat+numString = fmap tShow parseStrictFloat `onFail`- liftM tShow parseInt'+ fmap tShow parseInt' where tShow :: (Show a) => a -> Text tShow = T.pack . show stringBlock :: Parse Text-stringBlock = do frst <- satisfy frstIDString- rest <- manySatisfy restIDString- return $ frst `T.cons` rest+stringBlock = liftA2 T.cons (satisfy frstIDString) (manySatisfy restIDString) -- | Used when quotes are explicitly required; quotedString :: Parse Text quotedString = parseEscaped True [] [] parseSigned :: (Num a) => Parse a -> Parse a-parseSigned p = (character '-' >> liftM negate p)+parseSigned p = (character '-' *> fmap negate p) `onFail` p parseInt :: (Integral a) => Parse a parseInt = do cs <- many1Satisfy isDigit+ `adjustErr` ("Expected one or more digits\n\t"++) case T.decimal cs of- Right (n,"") -> return n+ Right (n,"") -> checkInt n+ -- This case should never actually happen... Right (_,txt) -> fail $ "Trailing digits not parsed as Integral: " ++ T.unpack txt Left err -> fail $ "Could not read Integral: " ++ err- `adjustErr` ("Expected one or more digits\n\t"++)+ where+ checkInt n = do c <- optional $ oneOf [ character '.', character 'e' ]+ if isJust c+ then fail "This number is actually Floating, not Integral!"+ else return n parseInt' :: Parse Int parseInt' = parseSigned parseInt@@ -265,9 +273,7 @@ parseFloat :: (RealFrac a) => Parse a parseFloat = do ds <- manySatisfy isDigit- frac <- optional- $ do character '.'- manySatisfy isDigit+ frac <- optional $ character '.' *> manySatisfy isDigit when (T.null ds && noDec frac) (fail "No actual digits in floating point number!") expn <- optional parseExp@@ -280,8 +286,8 @@ `onFail` fail "Expected a floating point number" where- parseExp = do character 'e'- ((character '+' >> parseInt)+ parseExp = character 'e'+ *> ((character '+' *> parseInt) `onFail` parseInt') noDec = maybe True T.null@@ -289,7 +295,7 @@ parseFloat' :: Parse Double parseFloat' = parseSigned ( parseFloat `onFail`- liftM fI parseInt+ fmap fI parseInt ) where fI :: Integer -> Double@@ -303,10 +309,9 @@ -- 'adjustErrBad' and thus doesn't allow backtracking and trying the -- next possible parser. This is a version of @bracket@ that does. bracket :: Parse bra -> Parse ket -> Parse a -> Parse a-bracket open close pa = do open `adjustErr` ("Missing opening bracket:\n\t"++)- pa `discard`- (close- `adjustErr` ("Missing closing bracket:\n\t"++))+bracket open close pa = (open `adjustErr` ("Missing opening bracket:\n\t"++))+ *> pa+ <* (close `adjustErr` ("Was expecting closing bracket:\n\t"++)) parseAndSpace :: Parse a -> Parse a parseAndSpace p = p `discard` whitespace@@ -318,7 +323,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 stringParse :: [(String, Parse a)] -> Parse a stringParse = toPM . sortBy (flip compare `on` fst)@@ -326,8 +331,8 @@ toPM = oneOf . map mkPM . groupBy ((==) `on` (listToMaybe . fst)) mkPM [("",p)] = p- mkPM [(str,p)] = string str >> p- mkPM kv = character (head . fst $ head kv) >> toPM (map (first tail) kv)+ mkPM [(str,p)] = string str *> p+ mkPM kv = character (head . fst $ head kv) *> toPM (map (first tail) kv) stringValue :: [(String, a)] -> Parse a stringValue = stringParse . map (second return)@@ -350,13 +355,13 @@ -- | Parses at least one whitespace character. whitespace1 :: Parse ()-whitespace1 = many1Satisfy isSpace >> return ()+whitespace1 = many1Satisfy isSpace *> return () -- | Parses zero or more whitespace characters. whitespace :: Parse ()-whitespace = manySatisfy isSpace >> return ()+whitespace = manySatisfy isSpace *> return () --- | Parse and discard optional whitespace.+-- | Parse and discard optional surrounding whitespace. wrapWhitespace :: Parse a -> Parse a wrapWhitespace = bracket whitespace whitespace @@ -371,8 +376,8 @@ quotedParse :: Parse a -> Parse a quotedParse = bracket parseQuote parseQuote -parseQuote :: Parse Char-parseQuote = character quoteChar+parseQuote :: Parse ()+parseQuote = character quoteChar *> return () orQuote :: Parse Char -> Parse Char orQuote p = stringRep quoteChar "\\\""@@ -388,7 +393,7 @@ -- 'Bool' value indicates whether empty 'String's are allowed or -- not. parseEscaped :: Bool -> [Char] -> [Char] -> Parse Text-parseEscaped empt cs bnd = liftM T.pack . lots $ qPrs `onFail` oth+parseEscaped empt cs bnd = fmap T.pack . lots $ qPrs `onFail` oth where lots = if empt then many else many1 cs' = quoteChar : slash : cs@@ -396,9 +401,10 @@ bndSet = Set.fromList bnd `Set.union` csSet slash = '\\' -- Have to allow standard slashes- qPrs = do character slash- mE <- optional $ oneOf (map character cs')- return $ fromMaybe slash mE+ qPrs = fromMaybe slash+ <$> (character slash+ *> optional (oneOf $ map character cs')+ ) oth = satisfy (`Set.notMember` bndSet) -- | Parses a newline.@@ -409,7 +415,7 @@ -- non-whitespace is reached. The whitespace on that line is -- not consumed. newline' :: Parse ()-newline' = many (whitespace >> newline) >> return ()+newline' = many (whitespace *> newline) *> return () -- | Parses and returns all characters up till the end of the line, -- but does not touch the newline characters.@@ -417,10 +423,10 @@ consumeLine = manySatisfy (`notElem` ['\n','\r']) parseEq :: Parse ()-parseEq = wrapWhitespace (character '=') >> return ()+parseEq = wrapWhitespace (character '=') *> return () parseField :: (ParseDot a) => (a -> b) -> String -> [(String, Parse b)]-parseField c fld = [(fld, parseEq >> liftM c parse)]+parseField c fld = [(fld, liftEqParse' fld c)] parseFields :: (ParseDot a) => (a -> b) -> [String] -> [(String, Parse b)] parseFields c = concatMap (parseField c)@@ -436,7 +442,7 @@ parseFieldDef :: (ParseDot a) => (a -> b) -> a -> String -> [(String, Parse b)] parseFieldDef c d fld = [(fld, p)] where- p = (parseEq >> liftM c parse)+ p = liftEqParse' fld c `onFail` do nxt <- optional $ satisfy restIDString bool (fail "Not actually the field you were after")@@ -446,6 +452,34 @@ parseFieldsDef :: (ParseDot a) => (a -> b) -> a -> [String] -> [(String, Parse b)] parseFieldsDef c d = concatMap (parseFieldDef c d) +-- | For numeric attributes, @dot -Tdot@ seems to use @\"\"@ to+-- indicate the default value.+parseFieldNumDef :: (ParseDot a) => (a -> b) -> a -> String -> [(String, Parse b)]+parseFieldNumDef c d fld = [(fld, liftEqParse p fld c)]+ where+ p = stringRep d "\"\""+ `onFail`+ parse++-- | 'liftEqParse'' using 'parse' as the parser.+liftEqParse' :: (ParseDot a) => String -> (a -> b) -> Parse b+liftEqParse' = liftEqParse parse++-- | Attempt to parse the @\"=value\"@ part of a @key=value@ pair. If+-- there is an equal sign but the @value@ part doesn't parse, throw+-- an un-recoverable error.+liftEqParse :: Parse a -> String -> (a -> b) -> Parse b+liftEqParse p k c = parseEq+ *> ( fmap c p+ `adjustErrBad`+ (("Unable to parse key=value with key of " ++ k+ ++ "\n\t") ++)+ )++-- | The opposite of 'bracket'.+ignoreSep :: (a -> b -> c) -> Parse a -> Parse sep -> Parse b -> Parse c+ignoreSep f pa sep pb = f <$> pa <* sep <*> pb+ commaSep :: (ParseDot a, ParseDot b) => Parse (a, b) commaSep = commaSep' parse parse @@ -453,19 +487,19 @@ commaSepUnqt = commaSep' parseUnqt parseUnqt commaSep' :: Parse a -> Parse b -> Parse (a,b)-commaSep' pa pb = do a <- pa- wrapWhitespace parseComma- b <- pb- return (a,b)+commaSep' pa pb = ignoreSep (,) pa (wrapWhitespace parseComma) pb parseComma :: Parse ()-parseComma = character ',' >> return ()+parseComma = character ',' *> return () +-- | Try to parse a list of the specified type; returns an empty list+-- if parsing fails. tryParseList :: (ParseDot a) => Parse [a] tryParseList = tryParseList' parse +-- | Return an empty list if parsing a list fails. tryParseList' :: Parse [a] -> Parse [a]-tryParseList' = liftM (fromMaybe []) . optional+tryParseList' = fmap (fromMaybe []) . optional parseAngled :: Parse a -> Parse a parseAngled = bracket (character '<') (character '>')@@ -482,13 +516,13 @@ parseColorScheme :: Bool -> Parse ColorScheme parseColorScheme scs = do cs <- oneOf [ stringRep X11 "X11" , stringRep SVG "svg"- , liftM Brewer parseUnqt+ , Brewer <$> parseUnqt ] when scs $ setColorScheme cs return cs instance ParseDot BrewerScheme where- parseUnqt = liftM2 BScheme parseUnqt parseUnqt+ parseUnqt = liftA2 BScheme parseUnqt parseUnqt instance ParseDot BrewerName where -- The order is different from above to make sure longer names are
Data/GraphViz/PreProcessing.hs view
@@ -16,8 +16,8 @@ * Split lines (by inserting a @\\@ the rest of that \"line\" is continued on the next line). - * 'Text's concatenated together using @\"...\" + \"...\"@; these- are concatenated into one big 'Text'.+ * Strings concatenated together using @\"...\" + \"...\"@; these+ are concatenated into one big string. -} module Data.GraphViz.PreProcessing(preProcess) where @@ -29,7 +29,6 @@ import qualified Data.Text.Lazy.Builder as B import Data.Text.Lazy.Builder(Builder) import Data.Monoid(Monoid(..), mconcat)-import Control.Monad(liftM) -- ----------------------------------------------------------------------------- -- Filtering out unwanted Dot items such as comments@@ -46,7 +45,7 @@ -- lines only over a single line. Should parse the /entire/ input -- 'Text'. parseOutUnwanted :: Parse Builder-parseOutUnwanted = liftM mconcat (many getNext)+parseOutUnwanted = mconcat <$> many getNext where getNext = parseOK `onFail`@@ -56,10 +55,11 @@ `onFail` parseUnwanted `onFail`- liftM B.singleton next- parseOK = liftM B.fromLazyText- $ many1Satisfy (`notElem` ['\n', '\r', '\\', '/', '"', '<'])+ fmap B.singleton next + parseOK = B.fromLazyText+ <$> many1Satisfy (`notElem` ['\n', '\r', '\\', '/', '"', '<'])+ -- | Parses an unwanted part of the Dot code (comments and -- pre-processor lines; also un-splits lines). parseUnwanted :: (Monoid m) => Parse m@@ -74,65 +74,58 @@ -- previous line, but will leave the one from the pre-processor line -- there (so in the end it just removes the line). parsePreProcessor :: (Monoid m) => Parse m-parsePreProcessor = do newline- character '#'- consumeLine- return mempty+parsePreProcessor = newline *> character '#' *> consumeLine *> pure mempty -- | Parse @//@-style comments. parseLineComment :: (Monoid m) => Parse m-parseLineComment = do string "//"- -- Note: do /not/ consume the newlines, as they're- -- needed in case the next line is a pre-processor- -- line.- consumeLine- return mempty+parseLineComment = string "//"+ -- Note: do /not/ consume the newlines, as they're+ -- needed in case the next line is a pre-processor+ -- line.+ *> consumeLine+ *> pure mempty -- | Parse @/* ... */@-style comments. parseMultiLineComment :: (Monoid m) => Parse m-parseMultiLineComment = bracket start end (many inner)- >> return mempty+parseMultiLineComment = bracket start end (many inner) *> pure mempty where start = string "/*" end = string "*/"- inner = (many1Satisfy ('*' /=) >> return ())+ inner = (many1Satisfy ('*' /=) *> pure ()) `onFail`- do character '*'- satisfy ('/' /=)- inner+ (character '*' *> satisfy ('/' /=) *> inner) parseConcatStrings :: Parse Builder-parseConcatStrings = liftM (wrapQuotes . mconcat)- $ sepBy1 parseString parseConcat+parseConcatStrings = wrapQuotes . mconcat <$> sepBy1 parseString parseConcat where qParse = bracket (character '"') (commit $ character '"')- parseString = qParse (liftM mconcat $ many parseInner)- parseInner = (string "\\\"" >> return (B.fromLazyText $ T.pack "\\\""))+ parseString = qParse (mconcat <$> many parseInner)+ parseInner = (string "\\\"" *> pure (B.fromLazyText $ T.pack "\\\"")) `onFail` -- Need to parse an explicit `\', in case it ends the -- string (and thus the next step would get parsed by the -- previous option).- (string "\\\\" >> return (B.fromLazyText $ T.pack "\\\\"))+ (string "\\\\" *> pure (B.fromLazyText $ T.pack "\\\\")) `onFail` parseSplitLine -- in case there's a split mid-quote `onFail`- liftM B.singleton (satisfy (quoteChar /=))- parseConcat = parseSep >> character '+' >> parseSep+ fmap B.singleton (satisfy (quoteChar /=))+ parseConcat = parseSep *> character '+' *> parseSep parseSep = many $ whitespace1 `onFail` parseUnwanted wrapQuotes str = qc `mappend` str `mappend` qc qc = B.singleton '"' -- | Lines can be split with a @\\@ at the end of the line. parseSplitLine :: (Monoid m) => Parse m-parseSplitLine = character '\\' >> newline >> return mempty+parseSplitLine = character '\\' *> newline *> pure mempty parseHTML :: Parse Builder-parseHTML = liftM (addAngled . mconcat)+parseHTML = fmap (addAngled . mconcat) . parseAngled $ many inner where inner = parseHTML `onFail`- (liftM B.fromLazyText $ many1Satisfy (\c -> c /= open && c /= close))+ (B.fromLazyText <$> many1Satisfy (\c -> c /= open && c /= close)) addAngled str = B.singleton open `mappend` str `mappend` B.singleton close open = '<' close = '>'
Data/GraphViz/Printing.hs view
@@ -78,7 +78,9 @@ , hPutDoc , Pretty(..) , bool- , string)+ , string+ , width+ , (<$>)) import qualified Text.PrettyPrint.Leijen.Text.Monadic as PP import qualified Data.Text.Lazy as T import Data.Text.Lazy(Text)
Data/GraphViz/Types/Canonical.hs view
@@ -91,7 +91,6 @@ import Data.GraphViz.Util(bool) import Control.Arrow((&&&))-import Control.Monad(liftM) -- ----------------------------------------------------------------------------- @@ -182,8 +181,8 @@ parseUnqt = parseSubGraph DotSG parseUnqt `onFail` -- Take "anonymous" DotSubGraphs into account.- liftM (DotSG False Nothing)- (parseBracesBased SubGraphAttribute parseUnqt)+ fmap (DotSG False Nothing)+ (parseBracesBased SubGraphAttribute parseUnqt) parse = parseUnqt -- Don't want the option of quoting `adjustErr`
Data/GraphViz/Types/Common.hs view
@@ -26,7 +26,7 @@ import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.Read as T import Data.Text.Lazy(Text)-import Control.Monad(liftM, liftM2, when)+import Control.Monad(when, unless) -- ----------------------------------------------------------------------------- -- This is re-exported by Data.GraphViz.Types@@ -49,9 +49,9 @@ toDot gID = unqtDot gID instance ParseDot GraphID where- parseUnqt = liftM stringNum parseUnqt+ parseUnqt = stringNum <$> parseUnqt - parse = liftM stringNum parse+ parse = stringNum <$> parse `adjustErr` ("Not a valid GraphID\n\t"++) @@ -115,13 +115,13 @@ oldTp <- getAttributeType maybe (return ()) setAttributeType mtp - as <- whitespace >> parse+ as <- whitespace *> parse -- Safe to set back even if not changed. setAttributeType oldTp return $ gat as `onFail`- liftM determineType parse+ fmap determineType parse parse = parseUnqt -- Don't want the option of quoting `adjustErr`@@ -184,14 +184,14 @@ parseList = parseUnqtList parseNodeID :: (ParseDot n) => Parse (Attributes -> DotNode n)-parseNodeID = liftM DotNode parseAndCheck+parseNodeID = DotNode <$> parseAndCheck where parseAndCheck = do n <- parse me <- optional parseUnwanted maybe (return n) (const notANode) me notANode = fail "This appears to be an edge, not a node"- parseUnwanted = oneOf [ parseEdgeType >> return ()- , character ':' >> return () -- PortPos value+ parseUnwanted = oneOf [ parseEdgeType *> return ()+ , character ':' *> return () -- PortPos value ] instance Functor DotNode where@@ -227,22 +227,20 @@ instance (ParseDot n) => ParseDot (DotEdge n) where- parseUnqt = parseAttrBased EdgeAttribute True parseEdgeID+ parseUnqt = parseAttrBased EdgeAttribute False parseEdgeID parse = parseUnqt -- Don't want the option of quoting -- Have to take into account edges of the type "n1 -> n2 -> n3", etc.- parseUnqtList = liftM concat- $ parseStatements parseEdgeLine+ parseUnqtList = concat <$> parseStatements parseEdgeLine parseList = parseUnqtList parseEdgeID :: (ParseDot n) => Parse (Attributes -> DotEdge n)-parseEdgeID = do eFrom <- parseEdgeNode- -- Parse both edge types just to be more liberal- parseEdgeType- eTo <- parseEdgeNode- return $ mkEdge eFrom eTo+parseEdgeID = ignoreSep mkEdge parseEdgeNode parseEdgeType parseEdgeNode+ `adjustErr`+ ("Parsed beginning of DotEdge but could not parse Attributes:\n\t"++)+ -- Parse both edge types just to be more liberal type EdgeNode n = (n, Maybe PortPos) @@ -254,11 +252,11 @@ $ parseStatements parseEdgeNode ) `onFail`- liftM return parseEdgeNode+ fmap (:[]) parseEdgeNode parseEdgeNode :: (ParseDot n) => Parse (EdgeNode n)-parseEdgeNode = liftM2 (,) parse- (optional $ character ':' >> parseEdgeBasedPP)+parseEdgeNode = liftA2 (,) parse+ (optional $ character ':' *> parseEdgeBasedPP) mkEdge :: EdgeNode n -> EdgeNode n -> Attributes -> DotEdge n mkEdge (eFrom, mFP) (eTo, mTP) = DotEdge eFrom eTo@@ -267,7 +265,7 @@ mkEdges :: [EdgeNode n] -> [EdgeNode n] -> Attributes -> [DotEdge n]-mkEdges fs ts as = liftM2 (\f t -> mkEdge f t as) fs ts+mkEdges fs ts as = liftA2 (\f t -> mkEdge f t as) fs ts addPortPos :: (PortPos -> Attribute) -> Maybe PortPos -> Attributes -> Attributes@@ -280,12 +278,11 @@ parseEdgeLine :: (ParseDot n) => Parse [DotEdge n] parseEdgeLine = do n1 <- parseEdgeNodes- ens <- many1 $ do parseEdgeType- parseEdgeNodes+ ens <- many1 $ parseEdgeType *> parseEdgeNodes let ens' = n1 : ens efs = zipWith mkEdges ens' (tail ens') ef = return $ \ as -> concatMap ($as) efs- parseAttrBased EdgeAttribute True ef+ parseAttrBased EdgeAttribute False ef instance Functor DotEdge where fmap f e = e { fromNode = f $ fromNode e@@ -351,8 +348,7 @@ parseGraphID :: (Bool -> Bool -> Maybe GraphID -> a) -> Parse a parseGraphID f = do whitespace- str <- liftM isJust- $ optional (parseAndSpace $ string strGraph)+ str <- isJust <$> optional (parseAndSpace $ string strGraph) dir <- parseAndSpace ( stringRep True dirGraph `onFail` stringRep False undirGraph@@ -390,7 +386,7 @@ parseBracesBased :: AttributeType -> Parse a -> Parse a parseBracesBased tp p = do gs <- getsGS id setAttributeType tp- a <- whitespace >> parseBraced (wrapWhitespace p)+ a <- whitespace *> parseBraced (wrapWhitespace p) modifyGS (const gs) return a `adjustErr`@@ -418,16 +414,15 @@ parseSubGraph :: (Bool -> Maybe GraphID -> stmt -> c) -> Parse stmt -> Parse c parseSubGraph pid pst = do (isC, fID) <- parseSubGraphID pid let tp = bool SubGraphAttribute ClusterAttribute isC- liftM fID $ parseBracesBased tp pst+ fID <$> parseBracesBased tp pst parseSubGraphID :: (Bool -> Maybe GraphID -> c) -> Parse (Bool,c)-parseSubGraphID f = do string sGraph- whitespace1- (isC,mid) <- parseSGID- return (isC, f isC mid)+parseSubGraphID f = appl <$> (string sGraph *> whitespace1 *> parseSGID)+ where+ appl (isC, mid) = (isC, f isC mid) parseSGID :: Parse (Bool, Maybe GraphID)-parseSGID = oneOf [ liftM getClustFrom $ parseAndSpace parse+parseSGID = oneOf [ getClustFrom <$> parseAndSpace parse , return (False, Nothing) ] where@@ -440,7 +435,7 @@ pStr = do isCl <- checkCl `onFail` return False- when isCl $ optional (character '_') >> return ()+ when isCl $ optional (character '_') *> return () sID <- optional pID let sID' = if sID == emptyID then Nothing@@ -451,7 +446,7 @@ -- For Strings, there are no more quotes to unescape, so consume -- what you can.- pID = liftM stringNum $ manySatisfy (const True)+ pID = stringNum <$> manySatisfy (const True) {- This is a much nicer definition, but unfortunately it doesn't work. The problem is that Graphviz decides that a subgraph is a cluster@@ -462,9 +457,9 @@ `onFail` return False sID <- optional $ do when isCl- $ optional (character '_') >> return ()+ $ optional (character '_') *> return () parseUnqt- when (isCl || isJust sID) $ whitespace1 >> return ()+ when (isCl || isJust sID) $ whitespace1 *> return () return (isCl, sID) -} @@ -474,8 +469,8 @@ printAttrBased prEmp ff ftp fas a = do oldType <- getAttributeType maybe (return ()) setAttributeType mtp oldCS <- getColorScheme- (dc <> semi) <* setAttributeType oldType- <* when prEmp (setColorScheme oldCS)+ (dc <> semi) <* unless prEmp (setColorScheme oldCS)+ <* setAttributeType oldType where mtp = ftp a f = ff a@@ -494,8 +489,8 @@ setAttributeType tp oldCS <- getColorScheme f <- p- atts <- tryParseList' (whitespace >> parse)- when lc $ setColorScheme oldCS+ atts <- tryParseList' (whitespace *> parse)+ unless lc $ setColorScheme oldCS when (tp /= oldType) $ setAttributeType oldType return $ f atts `adjustErr`@@ -507,16 +502,16 @@ -- | Parse the separator (and any other whitespace1 present) between statements. statementEnd :: Parse ()-statementEnd = parseSplit >> newline'+statementEnd = parseSplit *> newline' where- parseSplit = (whitespace >> oneOf [ character ';' >> return ()- , newline- ]+ parseSplit = (whitespace *> oneOf [ character ';' *> return ()+ , newline+ ] ) `onFail` whitespace1 parseStatements :: Parse a -> Parse [a]-parseStatements p = sepBy (whitespace >> p) statementEnd+parseStatements p = sepBy (whitespace *> p) statementEnd `discard` optional statementEnd
Data/GraphViz/Types/Generalised.hs view
@@ -74,7 +74,6 @@ import qualified Data.Foldable as F import qualified Data.Traversable as T import Control.Arrow((&&&))-import Control.Monad(liftM) import Control.Monad.Trans.State(get, put, modify, execState, evalState) -- -----------------------------------------------------------------------------@@ -154,7 +153,7 @@ printGStmts = toDot . F.toList parseGStmts :: (ParseDot n) => Parse (DotStatements n)-parseGStmts = liftM Seq.fromList parse+parseGStmts = Seq.fromList <$> parse statementStructure :: DotStatements n -> GraphState () statementStructure = F.mapM_ stmtStructure@@ -191,24 +190,24 @@ listToDot = unqtListToDot instance (ParseDot n) => ParseDot (DotStatement n) where- parseUnqt = oneOf [ liftM GA parseUnqt- , liftM SG parseUnqt- , liftM DN parseUnqt- , liftM DE parseUnqt+ parseUnqt = oneOf [ GA <$> parseUnqt+ , SG <$> parseUnqt+ , DN <$> parseUnqt+ , DE <$> parseUnqt ] parse = parseUnqt -- Don't want the option of quoting `adjustErr`- (++ "Not a valid statement")+ ("Not a valid statement\n\t"++) - parseUnqtList = liftM concat . wrapWhitespace+ parseUnqtList = fmap concat . wrapWhitespace $ parseStatements p where -- Have to do something special here because of "a -> b -> c" -- syntax for edges.- p = liftM (map DE) parseEdgeLine+ p = fmap (map DE) parseEdgeLine `onFail`- liftM return parse+ fmap (:[]) parse parseList = parseUnqtList @@ -262,14 +261,14 @@ parseUnqt = parseSubGraph DotSG parseGStmts `onFail` -- Take anonymous DotSubGraphs into account- liftM (DotSG False Nothing)- (parseBracesBased SubGraphAttribute parseGStmts)+ fmap (DotSG False Nothing)+ (parseBracesBased SubGraphAttribute parseGStmts) parse = parseUnqt -- Don't want the option of quoting `adjustErr`- (++ "\n\nNot a valid Sub Graph")+ ("Not a valid Sub Graph\n\t"++) - parseUnqtList = sepBy (whitespace >> parseUnqt) newline'+ parseUnqtList = sepBy (whitespace *> parseUnqt) newline' parseList = parseUnqtList @@ -298,8 +297,8 @@ newStmts = evalState (stsRe $ graphStatements dg) startN stsRe = T.mapM stRe- stRe (SG sg) = liftM SG $ sgRe sg- stRe stmt = return stmt+ stRe (SG sg) = SG <$> sgRe sg+ stRe stmt = pure stmt sgRe sg = do sgid' <- case subGraphID sg of Nothing -> do n <- get put $ succ n
Data/GraphViz/Types/Graph.hs view
@@ -114,8 +114,8 @@ import Data.Map(Map) import qualified Data.Set as S import qualified Data.Sequence as Seq+import Control.Applicative(liftA2, (<$>), (<*>)) import Control.Arrow((***))-import Control.Monad(liftM, liftM2) import Text.Read(Lexeme(Ident), lexP, parens, readPrec) import Text.ParserCombinators.ReadPrec(prec) @@ -361,7 +361,7 @@ lns = map (\ (n,ni) -> (n,(_inCluster ni, _attributes ni))) . M.assocs $ values dg - (cs,ns) = clustersToNodes pathOf id clustAs snd lns+ (cs,ns) = clustersToNodes pathOf (const True) id clustAs snd lns pathOf (n,(c,as)) = pathFrom c (n,as) pathFrom c ln = F.foldr C (N ln) . fromMaybe Seq.empty $ (`M.lookup`pM) =<< c@@ -471,7 +471,7 @@ invNs = usedClustsIn . M.map _inCluster $ values dg usedClustsIn = M.fromAscList- . map (liftM2 (,) (fst . head) (map snd))+ . map ((,) <$> fst . head <*> map snd) . groupSortBy fst . mapMaybe (uncurry (fmap . flip (,))) . M.assocs@@ -489,7 +489,7 @@ -- | Determine if this graph has nodes or clusters. isEmptyGraph :: DotGraph n -> Bool-isEmptyGraph = liftM2 (&&) isEmpty (not . hasClusters)+isEmptyGraph = liftA2 (&&) isEmpty (not . hasClusters) graphAttributes :: DotGraph n -> [GlobalAttributes] graphAttributes = fromGlobAttrs . graphAttrs@@ -575,7 +575,7 @@ -- | Uses the ParseDot instance for generalised 'G.DotGraph's. instance (Ord n, ParseDot n) => ParseDot (DotGraph n) where- parseUnqt = liftM fromGDot $ parseUnqt+ parseUnqt = fromGDot <$> parseUnqt where -- fromGDot :: G.DotGraph n -> DotGraph n fromGDot = fromDotRepr . flip asTypeOf (undefined :: G.DotGraph n)@@ -657,7 +657,7 @@ -> Map n (EdgeMap n) toEdgeMap f t = M.map eM . M.fromList . groupSortCollectBy f t' where- t' = liftM2 (,) t edgeAttributes+ t' = liftA2 (,) t edgeAttributes eM = M.fromList . groupSortCollectBy fst snd mapNs :: (Ord n, Ord n') => (n -> n') -> DotGraph n -> DotGraph n'
− FAQ
@@ -1,644 +0,0 @@-% FAQ-% Ivan Lazar Miljenovic--Fortuitously Anticipated Queries (FAQ)-======================================--Note that to distinguish it from [Graphviz], the library shall be-henceforth referred to as _graphviz_.--Graphviz vs _graphviz_-------------------------### What is the difference between Graphviz and _graphviz_? ###--[Graphviz] is an open source library and collection of utility-programs using that library to visualise [graphs] (which are specified-using the [Dot] language).--_graphviz_ is a library for the purely functional programming language-[Haskell] that provides "bindings" to Graphviz's programs. It does so-by allowing programmers to specify the layout of the graph and then-converts that to Dot code before calling the appropriate program to-perform the visualisation.--[Graphviz]: http://www.graphviz.org/-[graphs]: http://en.wikipedia.org/wiki/Graph_theory-[Dot]: http://www.graphviz.org/doc/info/lang.html-[Haskell]: http://haskell.org/--### Why should I use graphviz over one of the other Haskell Graphviz libraries? ###--Various Haskell libraries have support for Graphviz to one extent or-another; however _graphviz_ has the most comprehensive support-available out of all of them:--* There are [four different representations] of Dot graphs:-- 1. Canonical, which matches the layout of `dot -Tcanon`.- 2. Generalised, which allows statements to be in any order.- 3. A graph-based one that allows manipulation of the Dot graph.- 4. A monadic interface for embedding graphs in Haskell.-- There are also conversion functions between them.-- [four different representations]: #whats-the-difference-between-the-different-dotgraph-types--* The ability to parse and generate most aspects of Dot [syntax] and- [attributes]. This includes taking into account escaping and- quoting rules where applicable.-- [syntax]: http://graphviz.org/doc/info/lang.html- [attributes]: http://graphviz.org/doc/info/attrs.html--* The ability to use a custom node type for Dot graphs.--* Support for the all five layout algorithm programs and all specified- [output formats] as well as the ability to use custom programs, etc.-- [output formats]: http://www.graphviz.org/doc/info/output.html--* Functions to convert [FGL] graphs and other graph-like structures- (albeit not as nicely) to and from the internal Dot representations.- In future, this will be expanded to a much larger range of- graph-like values once a suitable abstraction is available.-- [FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/--* The ability to augment Dot and FGL graphs with positioning- information by round-trip passing through Graphviz.--* Pure Haskell implementations of `dot -Tcanon` and `tred`.--* _graphviz_ is continually being worked upon and expanded to better- suit/match the requirements of Graphviz, to improve performance and- to make it easier for the programmer to use.--### Is the API of _graphviz_ stable? ###--For the most part, yes: the only items that are likely to change in-the future are those with bugs/errors or if a radically better way of-doing things is found. For most uses, however, the API should not-change for the foreseeable future.--Note that _graphviz_'s version numbers follow the-[package versioning policy]; this means that you can immediately tell-when the API has had a backwards-incompatible change by comparing the-first two elements of the version. However, these changes won't-always affect most users.--[package versioning policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy--### What aspects of Dot syntax and attributes are covered? ###--It's easier to state which aspects of Dot [syntax] and [attributes]-_aren't_ covered:--#### Overall syntax items not covered ####--* Cannot specify a sub-graph as an end point in an edge;--* Comments, pre-processor lines and split lines are (currently) not- supported within HTML-like labels.--* _graphviz_ only uses UTF-8 encoding for printing and parsing- (whereas Graphviz allows Latin1 encoding with the `charset`- attribute).--* Graphviz is more liberal in accepting "invalid" values- (e.g. accepting a floating-point value when only integer values are- meant to be accepted); _graphviz_ is more strict in this aspect (and- will indeed throw an exception if it cannot parse something- properly).--* No extensions (e.g. postscript-specific attributes) are available.--#### Attribute and value items not covered ####--* The global `orientation` attribute is not defined; however its- behaviour is duplicated by the `rotate` attribute.--* The deprecated `overlap` algorithms have not been defined.--* `pointf` and `point` values have been combined into one datatype; as- such, when constructing values such as `Rect` care should be taken- about which parts of a `Point` are allowed.--* Only polygon-based `shape`s are available.--* The `charset` attribute is not available as _graphviz_ assumes that- all Dot graphs will be in UTF-8 for simplicity; if Latin1-encoded- graphs need to be parsed then you shall need to do all I/O for them- by hand.--* `colorscheme` attributes _are_ parsed, but the behaviour is not- quite the same: consider the following minimal Dot graph:-- ~~~~~ {.dot}- digraph {- a [ style=filled, fillcolor=gray, colorscheme=svg ]- }- ~~~~~-- Despite the fact that the color is specified before the colorscheme,- Graphviz will use that colorscheme to parse the color (as an SVG- gray differs from the X11 gray); _graphviz_, however, will use the- default colorscheme of `x11` to parse the color, and **then** set- the colorscheme to be `svg` (despite it not being used after it is- set).--#### Available items of note ####--There are a few items of note that are available that are worthy of-special note (as they may not be immediately obvious from the-generated documentation):--* _graphviz_ is able to parse (but not print) the following special- aspects of specifying edges in Dot code:-- - The `node:port` method of specifying of head/tail `portPos`- values.-- - Stating multiple edges with common interior nodes (e.g. `a -> b- -> c`).-- - Stating edges with a grouping of nodes (e.g. `a -> {b c}`).--* Sub-graphs are specified as being clusters when the subgraph name- starts with either `"cluster"` or `"cluster_"`; note that this- prefix is removed when determining the subraph's name for the- internal datatypes.--* Anonymous subgraphs (where not even the `subgraph` keyword is- specified) are also parseable.--* HTML-like and record labels are available, and feature proper- escaping/unescaping when printing/parsing.--* Other syntactic issues are taken care of for you automatically (such- as escaping/unescaping quotation marks). Even newlines are- automatically escaped (but not unescaped) for you, defaulting to- centered lines.--Getting _graphviz_ and more documentation--------------------------------------------### Where can I obtain _graphviz_? ###--The best place to get _graphviz_ is from its [HackageDB] page.--[HackageDB]: http://hackage.haskell.org/package/graphviz--### Where can I find the API documentation for _graphviz_? ###--Also on its [HackageDB] page.--### Is it safe to install and use _graphviz_ from its darcs repository? ###--No; unlike other projects I make no guarantees as to the stability of-the live version of _graphviz_. Whilst the [darcs] [repository] is-_usually_ stable, it's often in a state of flux and at times patches-that break the repository are recorded (when it's simpler/cleaner to-break one patch into several smaller patches).--[darcs]: http://darcs.net/-[repository]: http://code.haskell.org/graphviz/--### How is _graphviz_ licensed? ###--_graphviz_ is licensed under a [3-Clause BSD License] (note that the-ColorBrewer Color Schemes found in `Data.GraphViz.Attributes.Colors.Brewer`-are covered under-[their own license](http://graphviz.org/doc/info/colors.html#brewer_license)).--[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php--Simplistically, this means that you can do whatever you want with-_graphviz_ as long as you cite both myself and [Matthew Sackman] (the-original author) as being the authors of _graphviz_. However, I would-appreciate at least an [email] letting me know how _graphviz_ is being-used.--[Matthew Sackman]: http://www.wellquite.org/-[email]: mailto:Ivan.Miljenovic+graphviz@gmail.com--### Where can I find more information on _graphviz_? ###--From its [home page].--[home page]: http://projects.haskell.org/graphviz/--### Are there any tutorials on how to use _graphviz_? ###--A basic tutorial on-[how to visualise graph-like data](http://ivanmiljenovic.wordpress.com/2011/10/16/graphviz-in-vacuum/)-is available; more will come if people ask for it.--### What other packages use _graphviz_? ###--This is a list of all known packages that use _graphviz_: if you know-of any others please let me know and I'll add it to the list.--* [Graphalyze](http://hackage.haskell.org/package/Graphalyze)-* [SourceGraph](http://hackage.haskell.org/package/SourceGraph)--### What is the history of _graphviz_? ###--_graphviz_ was originally written by [Matthew Sackman] (if you want-his reasons for doing so, you'll have to ask him yourself) with the-first known release being on 10 July, 2008. In 2008 I (Ivan-Miljenovic) needed a library that provided bindings to Graphviz with-clustering support; at the time _graphviz_ was the most fully featured-and closest to what I wanted, so I submitted a patch that provided-support for both clustering and undirected graphs.--In April 2009, Matthew wanted to step down from maintaining _graphviz_-and asked if I wanted to take over. Since then the library has been-almost completely re-written with greatly improved coverage of the Dot-language and extra features. However, the original outline of the-library still remains.--Using _graphviz_-------------------### Can I start using _graphviz_ without knowing anything about Graphviz? ###--You can, but if you want to start doing anything more advanced then-you should be reading Graphviz's documentation as well as-_graphviz_'s. This is because the layout and design of _graphviz_ is-heavily based upon the Dot language and the various [attributes] that-Graphviz supports.--### Can I just use _graphviz_ without reading its documentation? ###--You should _at least_ read the various messages about possible-ambiguities, etc. at the top of each module and for the attributes you-use before you use _graphviz_.--### Do I need to have Graphviz installed to use _graphviz_? ###--Technically, no if you're only dealing with the Dot language aspects.-However, usage of the functions in the `Commands` module, or the-augmentation of pretty-printing functions in the GraphViz module _do_-require Graphviz to be installed.--### Why didn't you use FFI to bind to the Graphviz library? ###--Because I just kept working where [Matthew Sackman] left off and it-was already using Graphviz's tools rather than the actual library.-However, most other language bindings (for Python, Perl, etc.) seem to-do the same: generate Dot code and pass that to the relevant tool.--This, however, does provide a fortunate side effect where the ability-to print and parse Dot code means that _graphviz_ can be used for more-than just visualising graphs created solely in Haskell: it can also-import pre-defined graphs, or else generate Dot code for use with-other tools.--### What's the difference between the different DotGraph types? ###--_graphviz_ has four different "implementations" of Dot code:--**Canonical:**--: matches the output of `dot -Tcanon`. Recommended for use when- converting existing data into Dot (especially with the- `graphElemsToDot` function in `Data.GraphViz`).--**Generalised:**--: most closely matches the layout of actual Dot code, as such this is- preferred when parsing in arbitrary Dot graphs. Also useful in- cases where you want to use the common Graphviz "hack" of specifying- global attributes that don't apply to sub-graphs _after_ the- sub-graphs in question.--**Graph:**--: provides common graph operations on Dot graphs, based upon those- found in the [FGL].--**Monadic:**--: a nicer way of defining relatively static Dot graphs to embed within- Haskell code, etc. Loosely based (with permission!) upon Andy- Gill's [dotgen] library.--[dotgen]: http://hackage.haskell.org/package/dotgen--### What's the best way to parse Dot code? ###--In both cases below, you should use the `parseDotGraph` function to-parse the Dot code: this is because it will strip out comments and-pre-processor lines and join together split lines (if any of these-remain the parser will fail). Also, if you are not sure what the type-of the nodes are, use either String or else the `GraphID` type as it-explicitly caters for both Strings and numbers (whereas just assuming-it being a String will result in numbers being stored internally as a-String).--If you can, first run `dot -Tcanon` on the Dot code and parse it as a-`DotGraph` value. This is because `DotGraph` types are easier to deal-with.--If, however, this isn't possible (e.g. it uses an image that isn't in-the current working directory) then use the `GDotGraph` type.--### There are too many attributes!!! Which ones should I use? ###--The `Data.GraphViz.Attributes` module contains a cut-down list of-recommended and commonly used attributes.--The entire list of attributes can be found in-`Data.GraphViz.Attributes.Complete`. In particular, the following-attributes are **not** recommended for use:--* `Color` for anything except edge colours or gradients for nodes,- clusters and graphs when using Graphviz >= 2.29.0 (and if you must,- the border colour for a node).--* `ColorScheme`: just stick with X11 colours.--* `Comment`: pretty useless. Enough said.--### Can I use any attribute wherever I want? ###--No: attributes are all defined in one big datatype for the sake of-simplicity, but not all attributes are valid in all places. Read the-documentation (either for Graphviz or _graphviz_) to determine which is-suitable where.--### How can I use _graphviz_ to visualise non-FGL graphs? ###--The `graphElemsToDot` function allows you to visualise any graph for-which you can specify a list of labelled nodes and a list of labelled-edges.--### How can I use/process multiple graphs like Graphviz does? ###--At one stage, _graphviz_ supported dealing with lists of `DotGraph`s;-however, it was found to be faster to deal with each graph-individually rather than try to get Graphviz to deal with them all in-one go. In future, once the problem causing this has been tracked-down and fixed this feature will be returned.--### How can I use custom datatypes for node IDs? ###--The important thing here is to ensure that your custom datatype has-defined instances of `PrintDot` and `ParseDot`. Probably the easiest-way of doing this is to have functions that convert between your type-and `String` and let graphviz determine how to print and parse those.-Here is an example of a more difficult type that should be printed-like `"1: Foo"`:--~~~~~~~~~~~~~~~~~~~~ {.haskell}-data MyType = MyType String Int--instance PrintDot MyType where- unqtDot (MyType s i) = unqtDot i <> colon <+> unqtDot s-- -- We have a space in there, so we need quotes.- toDot = doubleQuotes . unqtDot--instance ParseDot MyType where- parseUnqt = do i <- parseUnqt- character ':'- whitespace1- s <- parseUnqt- return $ MyType s i-- -- Has at least one space, so it will be quoted.- parse = quotedParse parseUnqt-~~~~~~~~~~~~~~~~~~~~--Things to note from this example:--* Whilst `PrintDot` and `ParseDot` have default definitions for- `toDot` and `parse`, they assume the datatype doesn't need quotes;- as such if the value will- [need quoting](http://www.graphviz.org/doc/info/lang.html), then you- should do so explicitly.--* It is better to use the `PrintDot` instances for common types such- as `Int` and `String` rather than using the pretty-printers inbuilt- conversion functions (`int`, `text`, etc.) to ensure that- quotations, etc. are dealt with correctly.--* Be as liberal as you can when parsing, especially with whitespace:- when printing only one space is used, yet when parsing we use the- `whitespace1` parsing combinator that will parse all whitespace- characters (but it must consume _at least_ one; there is a variant- that does not need to parse any).--### When parsing Dot code, do I have to worry about the case? ###--Not at all: _graphviz_'s parser is case-insensitive; however, the-correct case is checked first so there is a slight degradation in-performance when the wrong case is used.--### How do I set portPos values for nodes in edges? ###--Graphviz allows you to specify edges such as `from:a -> to:b` where-the nodes "from" and "to" are defined with either `RecordLabel` or-`Html.Label` labels and have different sections; the edge is then drawn-from the "a" section of the "from" node to the "b" section of the "to"-node.--Whilst _graphviz_ can parse this, you can't define this yourself;-instead, do it the manual way:--~~~~~~~~~~~~~~~~~~~~ {.haskell}-DotEdge "from" "to" True [ TailPort (LabelledPort (PN "a") Nothing)- , HeadPort (LabelledPort (PN "b") Nothing)- ]-~~~~~~~~~~~~~~~~~~~~--I realise that doing this manually isn't as convenient, but I am open-to suggestions on how this can be improved.--Note where `TailPort` and `HeadPort` are used; the next question-explains this.--### Is there anything else I should know? ###--A few other things of note that you should know about:--* For an edge `a -> b`, Graphviz terms "a" to be the _tail_ node and- "b" to be the _head_ node.--* When creating `GraphID` values for the graphs and sub-graphs, you- should ensure that they won't clash with any of the `nodeID` values- when printed to avoid possible problems.--* It is a good idea to have unique IDs for sub-graphs to ensure that- global attributes are applied only to items in that sub-graph and so- that clusters aren't combined (it took me a _long_ time to find out- that this was the case).--* You should specify an ID for the overall graph when outputting to a- format such as SVG as it becomes the title of that image.--* Graphviz allows a node to be "defined" twice with different- attributes; in practice they are combined into one node. Running- Dot code through `dot -Tcanon` before parsing removes this problem.--* Several attributes are defined with taking a list of items; all of- these assume that the provided lists are non-empty (sub-values are a- different story).--* If a particular Dot graph is not parseable, the parser throws an- error rather than failing gracefully.--Design Decisions-------------------### Why does _graphviz_ use Polyparse rather than Parsec? ###--Short answer: because _graphviz_ was already using [Polyparse] when I-started working on it (and I hadn't done any parsing before so I had-no preference either way).--[Polyparse]: http://www.cs.york.ac.uk/fp/polyparse/--Longer answer: Polyparse has several advantages I feel over [Parsec]:--* Simpler types.-* Avoids the whole "but Parsec-3 is slower than Parsec-2" debate (with- its associated baggage/problems).-* Few inbuilt combinators: since there is no inbuilt `character`- parsing combinator, there are no problems with _graphviz_ using its- own case-less one.-* [Easier backtracking](http://www.cs.york.ac.uk/fp/polyparse/#how)--[Parsec]: http://hackage.haskell.org/package/parsec--### Why do you have four different representations of Dot graphs? ###--_graphviz_ has [four different representations] of Dot graphs. Apart-from the reasons given before, the canonical implementation was the-original representation, whereas the generalised one was only-introduced in the 2999.8.0.0 release and the other two in the-2999.12.0.0 release.--Note, however, that I was thinking of adding something like the-generalised implementation back around the time of the-[2999.0.0.0 release](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064436.html),-yet-[people didn't like the idea](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064442.html).--The graph-based implementation was added solely so I could write as-(un-yet finished) tutorial, and thought others might find it useful.-The monadic implementation came about as an attempt to encourage more-people to use _graphviz_ rather than other libraries such as [dotgen],-and I thought a nicer way of writing Dot graphs might help (the-initial plans involved complicated type-hackery to try and almost make-it a DSL for actual Dot code; however it ended up being too-complicated and unwieldy).--### Why are only FGL graphs supported? ###--Love them or hate them, [FGL] currently provides the best graph-datatype and library available for Haskell at this time. As such, if-any one graph type had to be chosen to have conversion functions-written for it then FGL is the best option. Furthermore, I needed FGL-graph support (which is the much more important reason!).--### Why are the version numbers so high? ###--To make sure the latest release has the highest version number:-Matthew Sackman originally made releases with date-based versioning,-but when I switched to using the [package versioning policy] I had to-change this. I could have started with 2010.x.y.z or so, but at the-time I had initial hopes of introducing compatibility with other-graphs (not just [FGL] ones) soon and wanted to make that the-3000.0.0.0 release; however that has not yet come to pass.--### Why do you use the American spelling of colour in _graphviz_? ###--Because that's how Graphviz spells it, and I was following upstream to-avoid confusion.--Bugs, Feature Requests and Development-----------------------------------------### Do you have any future plans for _graphviz_? ###--Yes, I do! See the TODO file for more information.--### Does _graphviz_ have a test suite? ###--Yes, there is: to get it, you have to build it with the `test` flag-enabled; for example:--~~~~~~~~~~~~~~~~~~~~ {.bash}-cabal install graphviz --flags=test-~~~~~~~~~~~~~~~~~~~~--Then run the `graphviz-testsuite` executable. This test suite uses-[QuickCheck] to ensure that _graphviz_ can parse the Dot code it-generates (as well as a few other things). Note that it isn't-perfect: there are no guarantees that the Dot graphs that are-generated are indeed valid, and those more extensive tests are not yet-available.--[QuickCheck]: http://hackage.haskell.org/package/QuickCheck--Furthermore, you can do more controlled testing to try and track down-the source of a bug as the above flag will also expose several-testing modules which give you access to the various tests used as-well as the `Arbitrary` instances for use with [QuickCheck].--For proper testing of real-life Dot code, there is also the-`TestParsing.hs` script that comes in the _graphviz_ tarball (but is-not installed). Once you have _graphviz_ installed you can just run-this script, passing it any files containing Dot graphs you wish to-test. It will attempt to parse each Dot graph as a `GDotGraph`, and-then test to see if the canonicalised form is parseable as a-`DotGraph`.--### I've found a bug! ###--Oh-oh... please [email] me the specifics of what you were doing-(including the Dot file in question if it's a parsing problem) and-I'll get right on it.--### I have a feature request. ###--Is it in the TODO? If not, [email] me and I'll consider implementing-it (depending on time and how well I think it will fit in the overall-library).--### I want to help out with developing _graphviz_. ###--Great! Whether you have a specific feature in mind or want to help-clear the TODO list, please [email] me to check with what you're doing-(who knows, I could already be implementing that very feature).--Once we've discussed what you're going to do, first get yourself a-copy of the darcs repository:--~~~~~~~~~~~~~~~~~~~~ {.bash}-darcs get --lazy http://code.haskell.org/graphviz-~~~~~~~~~~~~~~~~~~~~--Once you've made your changes, make sure you build and run the-testsuite (and ensure it passes!). Then record the patch[es] and-`darcs send` them. I'll then review them and if I'm happy with them,-I'll apply them.--### What is the purpose of the AttributeGenerator.hs file? ###--Graphviz has a large number of attributes. Rather than try to edit-everything manually each time I want to change how I use the large-`Attribute` datatype, the AttributeGenerator script generates the-datatype, instances, etc. for me.--<!--- Local Variables:- mode:markdown- End:- -->---<!-- LocalWords: graphviz- -->
+ FAQ.md view
@@ -0,0 +1,632 @@+% FAQ+% Ivan Lazar Miljenovic++Fortuitously Anticipated Queries (FAQ)+======================================++Note that to distinguish it from [Graphviz], the library shall be+henceforth referred to as _graphviz_.++Graphviz vs _graphviz_+----------------------++### What is the difference between Graphviz and _graphviz_? ###++[Graphviz] is an open source library and collection of utility+programs using that library to visualise [graphs] (which are specified+using the [Dot] language).++_graphviz_ is a library for the purely functional programming language+[Haskell] that provides "bindings" to Graphviz's programs. It does so+by allowing programmers to specify the layout of the graph and then+converts that to Dot code before calling the appropriate program to+perform the visualisation.++[Graphviz]: http://www.graphviz.org/+[graphs]: http://en.wikipedia.org/wiki/Graph_theory+[Dot]: http://www.graphviz.org/doc/info/lang.html+[Haskell]: http://haskell.org/++### Why should I use graphviz over one of the other Haskell Graphviz libraries? ###++Various Haskell libraries have support for Graphviz to one extent or+another; however _graphviz_ has the most comprehensive support+available out of all of them:++* There are [four different representations] of Dot graphs:++ 1. Canonical, which matches the layout of `dot -Tcanon`.+ 2. Generalised, which allows statements to be in any order.+ 3. A graph-based one that allows manipulation of the Dot graph.+ 4. A monadic interface for embedding graphs in Haskell.++ There are also conversion functions between them.++ [four different representations]: #whats-the-difference-between-the-different-dotgraph-types++* The ability to parse and generate most aspects of Dot [syntax] and+ [attributes]. This includes taking into account escaping and+ quoting rules where applicable.++ [syntax]: http://graphviz.org/doc/info/lang.html+ [attributes]: http://graphviz.org/doc/info/attrs.html++* The ability to use a custom node type for Dot graphs.++* Support for the all five layout algorithm programs and all specified+ [output formats] as well as the ability to use custom programs, etc.++ [output formats]: http://www.graphviz.org/doc/info/output.html++* Functions to convert [FGL] graphs and other graph-like structures+ (albeit not as nicely) to and from the internal Dot representations.+ In future, this will be expanded to a much larger range of+ graph-like values once a suitable abstraction is available.++ [FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/++* The ability to augment Dot and FGL graphs with positioning+ information by round-trip passing through Graphviz.++* Pure Haskell implementations of `dot -Tcanon` and `tred`.++* _graphviz_ is continually being worked upon and expanded to better+ suit/match the requirements of Graphviz, to improve performance and+ to make it easier for the programmer to use.++### Is the API of _graphviz_ stable? ###++For the most part, yes: the only items that are likely to change in+the future are those with bugs/errors or if a radically better way of+doing things is found. For most uses, however, the API should not+change for the foreseeable future.++Note that _graphviz_'s version numbers follow the+[package versioning policy]; this means that you can immediately tell+when the API has had a backwards-incompatible change by comparing the+first two elements of the version. However, these changes won't+always affect most users.++[package versioning policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy++### What aspects of Dot syntax and attributes are covered? ###++It's easier to state which aspects of Dot [syntax] and [attributes]+_aren't_ covered:++#### Overall syntax items not covered ####++* Cannot specify a sub-graph as an end point in an edge;++* Comments, pre-processor lines and split lines are (currently) not+ supported within HTML-like labels.++* _graphviz_ only uses UTF-8 encoding for printing and parsing+ (whereas Graphviz allows Latin1 encoding with the `charset`+ attribute).++* Graphviz is more liberal in accepting "invalid" values+ (e.g. accepting a floating-point value when only integer values are+ meant to be accepted); _graphviz_ is more strict in this aspect (and+ will indeed throw an exception if it cannot parse something+ properly).++* No extensions (e.g. postscript-specific attributes) are available.++#### Attribute and value items not covered ####++* The global `orientation` attribute is not defined; however its+ behaviour is duplicated by the `rotate` attribute.++* The deprecated `overlap` algorithms have not been defined.++* `pointf` and `point` values have been combined into one datatype; as+ such, when constructing values such as `Rect` care should be taken+ about which parts of a `Point` are allowed.++* Only polygon-based `shape`s are available.++* The `charset` attribute is not available as _graphviz_ assumes that+ all Dot graphs will be in UTF-8 for simplicity; if Latin1-encoded+ graphs need to be parsed then you shall need to do all I/O for them+ by hand.++* `colorscheme` attributes _are_ parsed, but the behaviour is not+ quite the same: consider the following minimal Dot graph:++ ~~~~~ {.dot}+ digraph {+ a [ style=filled, fillcolor=gray, colorscheme=svg ]+ }+ ~~~~~++ Despite the fact that the color is specified before the colorscheme,+ Graphviz will use that colorscheme to parse the color (as an SVG+ gray differs from the X11 gray); _graphviz_, however, will use the+ default colorscheme of `x11` to parse the color, and **then** set+ the colorscheme to be `svg` (despite it not being used after it is+ set).++#### Available items of note ####++There are a few items of note that are available that are worthy of+special note (as they may not be immediately obvious from the+generated documentation):++* _graphviz_ is able to parse (but not print) the following special+ aspects of specifying edges in Dot code:++ - The `node:port` method of specifying of head/tail `portPos`+ values.++ - Stating multiple edges with common interior nodes (e.g. `a -> b+ -> c`).++ - Stating edges with a grouping of nodes (e.g. `a -> {b c}`).++* Sub-graphs are specified as being clusters when the subgraph name+ starts with either `"cluster"` or `"cluster_"`; note that this+ prefix is removed when determining the subraph's name for the+ internal datatypes.++* Anonymous subgraphs (where not even the `subgraph` keyword is+ specified) are also parseable.++* HTML-like and record labels are available, and feature proper+ escaping/unescaping when printing/parsing.++* Other syntactic issues are taken care of for you automatically (such+ as escaping/unescaping quotation marks). Even newlines are+ automatically escaped (but not unescaped) for you, defaulting to+ centered lines.++Getting _graphviz_ and more documentation+-----------------------------------------++### Where can I obtain _graphviz_? ###++The best place to get _graphviz_ is from its [HackageDB] page.++[HackageDB]: http://hackage.haskell.org/package/graphviz++### Where can I find the API documentation for _graphviz_? ###++Also on its [HackageDB] page.++### Is it safe to install and use _graphviz_ from its darcs repository? ###++No; unlike other projects I make no guarantees as to the stability of+the live version of _graphviz_. Whilst the [darcs] [repository] is+_usually_ stable, it's often in a state of flux and at times patches+that break the repository are recorded (when it's simpler/cleaner to+break one patch into several smaller patches).++[darcs]: http://darcs.net/+[repository]: http://hub.darcs.net/ivanm/graphviz++### How is _graphviz_ licensed? ###++_graphviz_ is licensed under a [3-Clause BSD License] (note that the+ColorBrewer Color Schemes found in `Data.GraphViz.Attributes.Colors.Brewer`+are covered under+[their own license](http://graphviz.org/doc/info/colors.html#brewer_license)).++[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php++Simplistically, this means that you can do whatever you want with+_graphviz_ as long as you cite both myself and [Matthew Sackman] (the+original author) as being the authors of _graphviz_. However, I would+appreciate at least an [email] letting me know how _graphviz_ is being+used.++[Matthew Sackman]: http://www.wellquite.org/+[email]: mailto:Ivan.Miljenovic+graphviz@gmail.com++### Where can I find more information on _graphviz_? ###++From its [home page].++[home page]: http://projects.haskell.org/graphviz/++### Are there any tutorials on how to use _graphviz_? ###++A basic tutorial on+[how to visualise graph-like data](http://ivanmiljenovic.wordpress.com/2011/10/16/graphviz-in-vacuum/)+is available; more will come if people ask for it.++### What other packages use _graphviz_? ###++This is a list of all known packages that use _graphviz_: if you know+of any others please let me know and I'll add it to the list.++* [Graphalyze](http://hackage.haskell.org/package/Graphalyze)+* [SourceGraph](http://hackage.haskell.org/package/SourceGraph)++### What is the history of _graphviz_? ###++_graphviz_ was originally written by [Matthew Sackman] (if you want+his reasons for doing so, you'll have to ask him yourself) with the+first known release being on 10 July, 2008. In 2008 I (Ivan+Miljenovic) needed a library that provided bindings to Graphviz with+clustering support; at the time _graphviz_ was the most fully featured+and closest to what I wanted, so I submitted a patch that provided+support for both clustering and undirected graphs.++In April 2009, Matthew wanted to step down from maintaining _graphviz_+and asked if I wanted to take over. Since then the library has been+almost completely re-written with greatly improved coverage of the Dot+language and extra features. However, the original outline of the+library still remains.++Using _graphviz_+----------------++### Can I start using _graphviz_ without knowing anything about Graphviz? ###++You can, but if you want to start doing anything more advanced then+you should be reading Graphviz's documentation as well as+_graphviz_'s. This is because the layout and design of _graphviz_ is+heavily based upon the Dot language and the various [attributes] that+Graphviz supports.++### Can I just use _graphviz_ without reading its documentation? ###++You should _at least_ read the various messages about possible+ambiguities, etc. at the top of each module and for the attributes you+use before you use _graphviz_.++### Do I need to have Graphviz installed to use _graphviz_? ###++Technically, no if you're only dealing with the Dot language aspects.+However, usage of the functions in the `Commands` module, or the+augmentation of pretty-printing functions in the GraphViz module _do_+require Graphviz to be installed.++### Why didn't you use FFI to bind to the Graphviz library? ###++Because I just kept working where [Matthew Sackman] left off and it+was already using Graphviz's tools rather than the actual library.+However, most other language bindings (for Python, Perl, etc.) seem to+do the same: generate Dot code and pass that to the relevant tool.++This, however, does provide a fortunate side effect where the ability+to print and parse Dot code means that _graphviz_ can be used for more+than just visualising graphs created solely in Haskell: it can also+import pre-defined graphs, or else generate Dot code for use with+other tools.++### What's the difference between the different DotGraph types? ###++_graphviz_ has four different "implementations" of Dot code:++**Canonical:**++: matches the output of `dot -Tcanon`. Recommended for use when+ converting existing data into Dot (especially with the+ `graphElemsToDot` function in `Data.GraphViz`).++**Generalised:**++: most closely matches the layout of actual Dot code, as such this is+ preferred when parsing in arbitrary Dot graphs. Also useful in+ cases where you want to use the common Graphviz "hack" of specifying+ global attributes that don't apply to sub-graphs _after_ the+ sub-graphs in question.++**Graph:**++: provides common graph operations on Dot graphs, based upon those+ found in the [FGL].++**Monadic:**++: a nicer way of defining relatively static Dot graphs to embed within+ Haskell code, etc. Loosely based (with permission!) upon Andy+ Gill's [dotgen] library.++[dotgen]: http://hackage.haskell.org/package/dotgen++### What's the best way to parse Dot code? ###++In both cases below, you should use the `parseDotGraph` function to+parse the Dot code: this is because it will strip out comments and+pre-processor lines and join together split lines (if any of these+remain the parser will fail). Also, if you are not sure what the type+of the nodes are, use either String or else the `GraphID` type as it+explicitly caters for both Strings and numbers (whereas just assuming+it being a String will result in numbers being stored internally as a+String).++If you can, first run `dot -Tcanon` on the Dot code and parse it as a+`DotGraph` value. This is because `DotGraph` types are easier to deal+with.++If, however, this isn't possible (e.g. it uses an image that isn't in+the current working directory) then use the `GDotGraph` type.++### There are too many attributes!!! Which ones should I use? ###++The `Data.GraphViz.Attributes` module contains a cut-down list of+recommended and commonly used attributes.++The entire list of attributes can be found in+`Data.GraphViz.Attributes.Complete`. In particular, the following+attributes are **not** recommended for use:++* `Color` for anything except edge colours or gradients for nodes,+ clusters and graphs when using Graphviz >= 2.29.0 (and if you must,+ the border colour for a node).++* `ColorScheme`: just stick with X11 colours.++* `Comment`: pretty useless. Enough said.++### Can I use any attribute wherever I want? ###++No: attributes are all defined in one big datatype for the sake of+simplicity, but not all attributes are valid in all places. Read the+documentation (either for Graphviz or _graphviz_) to determine which is+suitable where.++### How can I use _graphviz_ to visualise non-FGL graphs? ###++The `graphElemsToDot` function allows you to visualise any graph for+which you can specify a list of labelled nodes and a list of labelled+edges.++### How can I use/process multiple graphs like Graphviz does? ###++At one stage, _graphviz_ supported dealing with lists of `DotGraph`s;+however, it was found to be faster to deal with each graph+individually rather than try to get Graphviz to deal with them all in+one go. In future, once the problem causing this has been tracked+down and fixed this feature will be returned.++### How can I use custom datatypes for node IDs? ###++The important thing here is to ensure that your custom datatype has+defined instances of `PrintDot` and `ParseDot`. Probably the easiest+way of doing this is to have functions that convert between your type+and `String` or `Text` and let graphviz determine how to print and+parse those. Here is an example of a more difficult type that should+be printed like `"1: Foo"`:++~~~~~~~~~~~~~~~~~~~~ {.haskell}+data MyType = MyType String Int++instance PrintDot MyType where+ unqtDot (MyType s i) = unqtDot i <> colon <+> unqtDot s++ -- We have a space in there, so we need quotes.+ toDot = doubleQuotes . unqtDot++instance ParseDot MyType where+ parseUnqt = MyType <$> parseUnqt+ <* character ':'+ <* whitespace1+ <*> parseUnqt++ -- Has at least one space, so it will be quoted.+ parse = quotedParse parseUnqt+~~~~~~~~~~~~~~~~~~~~++Things to note from this example:++* Whilst `PrintDot` and `ParseDot` have default definitions for+ `toDot` and `parse`, they assume the datatype doesn't need quotes;+ as such if the value will+ [need quoting](http://www.graphviz.org/doc/info/lang.html), then you+ should do so explicitly.++* It is better to use the `PrintDot` instances for common types such+ as `Int` and `String` rather than using the pretty-printers inbuilt+ conversion functions (`int`, `text`, etc.) to ensure that+ quotations, etc. are dealt with correctly.++* Be as liberal as you can when parsing, especially with whitespace:+ when printing only one space is used, yet when parsing we use the+ `whitespace1` parsing combinator that will parse all whitespace+ characters (but it must consume _at least_ one; there is a variant+ that does not need to parse any).++### When parsing Dot code, do I have to worry about the case? ###++Not at all: _graphviz_'s parser is case-insensitive; however, the+correct case is checked first so there is a slight degradation in+performance when the wrong case is used.++### How do I set portPos values for nodes in edges? ###++Graphviz allows you to specify edges such as `from:a -> to:b` where+the nodes "from" and "to" are defined with either `RecordLabel` or+`Html.Label` labels and have different sections; the edge is then drawn+from the "a" section of the "from" node to the "b" section of the "to"+node.++Whilst _graphviz_ can parse this, you can't define this yourself;+instead, do it the manual way:++~~~~~~~~~~~~~~~~~~~~ {.haskell}+DotEdge "from" "to" True [ TailPort (LabelledPort (PN "a") Nothing)+ , HeadPort (LabelledPort (PN "b") Nothing)+ ]+~~~~~~~~~~~~~~~~~~~~++I realise that doing this manually isn't as convenient, but I am open+to suggestions on how this can be improved.++Note where `TailPort` and `HeadPort` are used; the next question+explains this.++### Is there anything else I should know? ###++A few other things of note that you should know about:++* For an edge `a -> b`, Graphviz terms "a" to be the _tail_ node and+ "b" to be the _head_ node.++* When creating `GraphID` values for the graphs and sub-graphs, you+ should ensure that they won't clash with any of the `nodeID` values+ when printed to avoid possible problems.++* It is a good idea to have unique IDs for sub-graphs to ensure that+ global attributes are applied only to items in that sub-graph and so+ that clusters aren't combined (it took me a _long_ time to find out+ that this was the case).++* You should specify an ID for the overall graph when outputting to a+ format such as SVG as it becomes the title of that image.++* Graphviz allows a node to be "defined" twice with different+ attributes; in practice they are combined into one node. Running+ Dot code through `dot -Tcanon` before parsing removes this problem.++* Several attributes are defined with taking a list of items; all of+ these assume that the provided lists are non-empty (sub-values are a+ different story).++* If a particular Dot graph is not parseable, the parser throws an+ error rather than failing gracefully.++Design Decisions+----------------++### Why does _graphviz_ use Polyparse rather than Parsec? ###++Short answer: because _graphviz_ was already using [Polyparse] when I+started working on it (and I hadn't done any parsing before so I had+no preference either way).++[Polyparse]: http://www.cs.york.ac.uk/fp/polyparse/++Longer answer: Polyparse has several advantages I feel over [Parsec]:++* Simpler types.+* Avoids the whole "but Parsec-3 is slower than Parsec-2" debate (with+ its associated baggage/problems).+* Few inbuilt combinators: since there is no inbuilt `character`+ parsing combinator, there are no problems with _graphviz_ using its+ own case-less one.+* [Easier backtracking](http://www.cs.york.ac.uk/fp/polyparse/#how)++[Parsec]: http://hackage.haskell.org/package/parsec++### Why do you have four different representations of Dot graphs? ###++_graphviz_ has [four different representations] of Dot graphs. Apart+from the reasons given before, the canonical implementation was the+original representation, whereas the generalised one was only+introduced in the 2999.8.0.0 release and the other two in the+2999.12.0.0 release.++Note, however, that I was thinking of adding something like the+generalised implementation back around the time of the+[2999.0.0.0 release](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064436.html),+yet+[people didn't like the idea](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064442.html).++The graph-based implementation was added solely so I could write as+(un-yet finished) tutorial, and thought others might find it useful.+The monadic implementation came about as an attempt to encourage more+people to use _graphviz_ rather than other libraries such as [dotgen],+and I thought a nicer way of writing Dot graphs might help (the+initial plans involved complicated type-hackery to try and almost make+it a DSL for actual Dot code; however it ended up being too+complicated and unwieldy).++### Why are only FGL graphs supported? ###++Love them or hate them, [FGL] currently provides the best graph+datatype and library available for Haskell at this time. As such, if+any one graph type had to be chosen to have conversion functions+written for it then FGL is the best option. Furthermore, I needed FGL+graph support (which is the much more important reason!).++### Why are the version numbers so high? ###++To make sure the latest release has the highest version number:+Matthew Sackman originally made releases with date-based versioning,+but when I switched to using the [package versioning policy] I had to+change this. I could have started with 2010.x.y.z or so, but at the+time I had initial hopes of introducing compatibility with other+graphs (not just [FGL] ones) soon and wanted to make that the+3000.0.0.0 release; however that has not yet come to pass.++### Why do you use the American spelling of colour in _graphviz_? ###++Because that's how Graphviz spells it, and I was following upstream to+avoid confusion.++Bugs, Feature Requests and Development+--------------------------------------++### Do you have any future plans for _graphviz_? ###++Yes, I do! See the TODO file for more information.++### Does _graphviz_ have a test suite? ###++Yes, there is, using the in-built support for test suites in Cabal:++~~~~~~~~~~~~~~~~~~~~ {.bash}+cabal install graphviz --enable-tests+~~~~~~~~~~~~~~~~~~~~++Then run the `graphviz-testsuite` executable. This test suite uses+[QuickCheck] to ensure that _graphviz_ can parse the Dot code it+generates (as well as a few other things). Note that it isn't+perfect: there are no guarantees that the Dot graphs that are+generated are indeed valid, and those more extensive tests are not yet+available.++[QuickCheck]: http://hackage.haskell.org/package/QuickCheck++Furthermore, you can do more controlled testing to try and track down+the source of a bug as the above flag will also expose several+testing modules which give you access to the various tests used as+well as the `Arbitrary` instances for use with [QuickCheck].++For proper testing of real-life Dot code, there is also the+`TestParsing.hs` script that comes in the _graphviz_ tarball (but is+not installed). Once you have _graphviz_ installed you can just run+this script, passing it any files containing Dot graphs you wish to+test. It will attempt to parse each Dot graph as a `GDotGraph`, and+then test to see if the canonicalised form is parseable as a+`DotGraph`.++### I've found a bug! ###++Oh-oh... please [email] me the specifics of what you were doing+(including the Dot file in question if it's a parsing problem) and+I'll get right on it.++### I have a feature request. ###++Is it in the TODO? If not, [email] me and I'll consider implementing+it (depending on time and how well I think it will fit in the overall+library).++### I want to help out with developing _graphviz_. ###++Great! Whether you have a specific feature in mind or want to help+clear the TODO list, please [email] me to check with what you're doing+(who knows, I could already be implementing that very feature).++Once we've discussed what you're going to do, first get yourself a+copy of the darcs repository:++~~~~~~~~~~~~~~~~~~~~ {.bash}+darcs get --lazy http://hub.darcs.net/ivanm/graphviz+~~~~~~~~~~~~~~~~~~~~++Once you've made your changes, make sure you build and run the+testsuite (and ensure it passes!). Then record the patch[es] and+`darcs send` them. I'll then review them and if I'm happy with them,+I'll apply them.++### What is the purpose of the AttributeGenerator.hs file? ###++Graphviz has a large number of attributes. Rather than try to edit+everything manually each time I want to change how I use the large+`Attribute` datatype, the AttributeGenerator script generates the+datatype, instances, etc. for me.
− LICENSE
@@ -1,106 +0,0 @@-% License-% Ivan Lazar Miljenovic--Licensing Information-=====================--The overall graphviz library is covered by a [3-Clause BSD License].-However, the _ColorBrewer_ colours are licensed under their own-license.--[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php--License for graphviz-----------------------Copyright (c) 2008, Matthew Sackman--Copyright (c) 2008 - 2010, [Ivan Lazar Miljenovic](mailto:Ivan.Miljenovic+graphviz@gmail.com)--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are-met:-- * Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials- provided with the distribution.-- * The names of the contributors to this software may not be used- to endorse or promote products derived from this software- without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS 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 THE COPYRIGHT-OWNER OR CONTRIBUTORS 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.--The ColorBrewer license--------------------------> The _ColorBrewer_ colours and colour schemes found in-> `Data.GraphViz.Attributes.Colors` are covered by the following-> license. This text is not part of the 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.--<!--- Local Variables:- mode:markdown- End:- -->
+ LICENSE.md view
@@ -0,0 +1,100 @@+% License+% Ivan Lazar Miljenovic++Licensing Information+=====================++The overall graphviz library is covered by a [3-Clause BSD License].+However, the _ColorBrewer_ colours are licensed under their own+license.++[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php++License for graphviz+--------------------++Copyright (c) 2008, Matthew Sackman++Copyright (c) 2008 - 2010, [Ivan Lazar Miljenovic](mailto:Ivan.Miljenovic+graphviz@gmail.com)++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials+ provided with the distribution.++ * The names of the contributors to this software may not be used+ to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS 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 THE COPYRIGHT+OWNER OR CONTRIBUTORS 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.++The ColorBrewer license+-----------------------++> The _ColorBrewer_ colours and colour schemes found in+> `Data.GraphViz.Attributes.Colors` are covered by the following+> license. This text is not part of the 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
@@ -1,64 +0,0 @@-% Haskell bindings to the Graphviz toolkit-% Ivan Lazar Miljenovic--The graphviz Library-====================--The _graphviz_ library provides bindings to the [Graphviz] graph-visualisation suite of tools for the purely functional programming-language [Haskell]. It can be downloaded from [HackageDB] or - if you-have [cabal-install] - installing it is as simple as:--~~~~~~~~~~~~~~~~~~~~ {.bash}-cabal update-cabal install graphviz-~~~~~~~~~~~~~~~~~~~~--[Graphviz]: http://www.graphviz.org/-[Haskell]: http://haskell.org/-[HackageDB]: http://hackage.haskell.org/package/graphviz-[cabal-install]: http://haskell.org/haskellwiki/Cabal-Install--Library features-------------------Main features of the graphviz library include:--* Almost complete coverage of all Graphviz attributes and syntax.--* 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 with two- options: strict and liberal (in terms of ordering of statements).--* Functions to convert [FGL] graphs and other graph-like data- structures to Dot code - including support to group them into- clusters - with a high degree of customisation by specifying which- attributes to use and limited support for the inverse operation.--* Round-trip support for passing an [FGL] graph through Graphviz to- augment node and edge labels with positional information, etc.--[FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/--graphviz is free software licensed under a [3-Clause BSD License].--\(C\) 2008 [Matthew Sackman](http://www.wellquite.org/)--\(C\) 2008 - onwards [Ivan Lazar Miljenovic](http://ivanmiljenovic.wordpress.com/)--[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php--For more information, feel free to-[email](mailto:Ivan.Miljenovic+graphviz@gmail.com) me.--<!--- Local Variables:- mode:markdown- End:- -->
+ README.md view
@@ -0,0 +1,58 @@+% Haskell bindings to the Graphviz toolkit+% Ivan Lazar Miljenovic++The graphviz Library+====================++The _graphviz_ library provides bindings to the [Graphviz] graph+visualisation suite of tools for the purely functional programming+language [Haskell]. It can be downloaded from [HackageDB] or - if you+have [cabal-install] - installing it is as simple as:++~~~~~~~~~~~~~~~~~~~~ {.bash}+cabal update+cabal install graphviz+~~~~~~~~~~~~~~~~~~~~++[Graphviz]: http://www.graphviz.org/+[Haskell]: http://haskell.org/+[HackageDB]: http://hackage.haskell.org/package/graphviz+[cabal-install]: http://haskell.org/haskellwiki/Cabal-Install++Library features+----------------++Main features of the graphviz library include:++* Almost complete coverage of all Graphviz attributes and syntax.++* 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 with two+ options: strict and liberal (in terms of ordering of statements).++* Functions to convert [FGL] graphs and other graph-like data+ structures to Dot code - including support to group them into+ clusters - with a high degree of customisation by specifying which+ attributes to use and limited support for the inverse operation.++* Round-trip support for passing an [FGL] graph through Graphviz to+ augment node and edge labels with positional information, etc.++[FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/++graphviz is free software licensed under a [3-Clause BSD License].++\(C\) 2008 [Matthew Sackman](http://www.wellquite.org/)++\(C\) 2008 - onwards [Ivan Lazar Miljenovic](http://ivanmiljenovic.wordpress.com/)++[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php++For more information, feel free to+[email](mailto:Ivan.Miljenovic+graphviz@gmail.com) me.
− TODO
@@ -1,54 +0,0 @@-% TODO-% Ivan Lazar Miljenovic--Future Plans for graphviz-=========================--This is a list of planned feature improvements to graphviz along with-an indication of when it's likely to be implemented (note that these-time scales are in relation to releases, not actual time; however, it-is quite possible that the order will not be adhered to).--Short term-------------* Quickstart-style documentation to help users get going with graphviz- quickly.--* Add nicer syntax for record labels, and specifying ports in Monadic- Dot graphs.--* Define new classes to distinguish between printing/parsing Attribute- values and other values (as only the former requires quoted- variants).--* Clean up AttributeGenerator and get it to use a better- pretty-printing library.--Medium term--------------* Improve the test suite such that the generated `DotGraph` values are- valid (and thus can be passed to Graphviz proper). This may not in- fact be possible as guaranteeing an arbitrary `Attribute` is valid- is rather tricky (as the value itself needs to be verified,- especially stateful ones).--* Switch to a proper test-suite library rather than the hand-rolled- one currently being used.--* Add support for clusters as endpoints of edges.--Long term------------* Allow usage of non-FGL graphs with graphviz. This will require- implementing a separate library to represent graphs (see initial- discussions about this- [here](http://www.haskell.org/pipermail/haskell-cafe/2009-June/063402.html)).--<!--- Local Variables:- mode:markdown- End:- -->
+ TODO.md view
@@ -0,0 +1,48 @@+% TODO+% Ivan Lazar Miljenovic++Future Plans for graphviz+=========================++This is a list of planned feature improvements to graphviz along with+an indication of when it's likely to be implemented (note that these+time scales are in relation to releases, not actual time; however, it+is quite possible that the order will not be adhered to).++Short term+----------++* Quickstart-style documentation to help users get going with graphviz+ quickly.++* Add nicer syntax for record labels, and specifying ports in Monadic+ Dot graphs.++* Define new classes to distinguish between printing/parsing Attribute+ values and other values (as only the former requires quoted+ variants).++* Clean up AttributeGenerator and get it to use a better+ pretty-printing library.++Medium term+-----------++* Improve the test suite such that the generated `DotGraph` values are+ valid (and thus can be passed to Graphviz proper). This may not in+ fact be possible as guaranteeing an arbitrary `Attribute` is valid+ is rather tricky (as the value itself needs to be verified,+ especially stateful ones).++* Switch to a proper test-suite library rather than the hand-rolled+ one currently being used.++* Add support for clusters as endpoints of edges.++Long term+---------++* Allow usage of non-FGL graphs with graphviz. This will require+ implementing a separate library to represent graphs (see initial+ discussions about this+ [here](http://www.haskell.org/pipermail/haskell-cafe/2009-June/063402.html)).
graphviz.cabal view
@@ -1,5 +1,5 @@ Name: graphviz-Version: 2999.14.1.0+Version: 2999.15.0.0 Stability: Beta Synopsis: Bindings to Graphviz for graph visualisation. Description: {@@ -33,22 +33,23 @@ Homepage: http://projects.haskell.org/graphviz/ Category: Graphs, Graphics License: BSD3-License-File: LICENSE+License-File: LICENSE.md Copyright: Matthew Sackman, Ivan Lazar Miljenovic Author: Matthew Sackman, Ivan Lazar Miljenovic Maintainer: Ivan.Miljenovic+graphviz@gmail.com+Bug-Reports: http://hub.darcs.net/ivanm/graphviz/issues Build-Type: Simple Cabal-Version: >= 1.14-Extra-Source-Files: TODO- Changelog- README- FAQ+Extra-Source-Files: TODO.md+ Changelog.md+ README.md+ FAQ.md utils/AttributeGenerator.hs utils/TestParsing.hs Source-Repository head Type: darcs- Location: http://code.haskell.org/graphviz+ Location: http://hub.darcs.net/ivanm/graphviz Library { Default-Language: Haskell98@@ -60,7 +61,7 @@ fgl == 5.4.*, filepath, polyparse >= 1.7 && < 1.9,- bytestring == 0.9.*,+ bytestring >= 0.9 && < 0.11, colour == 2.3.*, transformers >= 0.2 && < 0.4, text,@@ -115,6 +116,7 @@ Build-Depends: base, containers, process,+ directory, fgl, filepath, polyparse,@@ -124,7 +126,7 @@ text, wl-pprint-text, dlist,- QuickCheck >= 2.3 && < 2.5+ QuickCheck >= 2.3 && < 2.6 hs-Source-Dirs: . tests
tests/Data/GraphViz/Testing/Instances/Attributes.hs view
@@ -439,6 +439,16 @@ shrink (DVal d) = map DVal $ shrink d shrink (PVal p) = map PVal $ shrink p +instance Arbitrary SVGFontNames where+ arbitrary = arbBounded++instance Arbitrary GraphSize where+ arbitrary = liftM3 GSize arbitrary arbitrary arbitrary++ shrink gs = do w' <- shrink $ width gs+ h' <- shrinkM $ height gs+ return $ GSize w' h' False+ instance Arbitrary ModeType where arbitrary = arbBounded
utils/AttributeGenerator.hs view
@@ -67,6 +67,7 @@ , parseNames :: [Code] , valtype :: VType , parseDef :: Maybe Code+ , emptyParse :: Maybe Code -- ^ What the empty string gets parsed as. , defValue :: Maybe Code , forGraphs :: Bool , forClusters :: Bool@@ -87,6 +88,7 @@ , valtype = v -- just in case need to do fancy -- stuff , parseDef = liftM text df+ , emptyParse = liftM text dfP , defValue = liftM text d , forGraphs = isFor 'G' , forClusters = isFor 'C' || forSG@@ -100,6 +102,11 @@ isFor f = f `elem` u forSG = isFor 'S' df' = if v == Bl then Just "'True'" else fmap ( \ t -> '\'' : t ++ "'") df+ isNumeric = case v of+ Integ -> True+ Dbl -> True+ _ -> False+ dfP = bool Nothing d isNumeric mDoc (f,fc) = f <> colon <+> text fc addF f = fmap (\ dc -> (wrap (char '/') (text f), dc)) cm' = hsep@@ -148,14 +155,14 @@ . asRows . firstOthers equals (char '|') . (++ [defUnknown])- . map createDefn+ . map createDf $ atts att derivs = nest tab $ text "deriving (Eq, Ord, Show, Read)"- createDefn a = [cnst a <+> vtypeCode a- , if isEmpty cm- then empty- else text "-- ^" <+> cm- ]+ createDf a = [cnst a <+> vtypeCode a+ , if isEmpty cm+ then empty+ else text "-- ^" <+> cm+ ] where cm = comment a defUnknown = [ unknownAttr <+> unknownNameAlias <+> vtype Strng@@ -170,17 +177,19 @@ where tp = tpNm att -nameAlias :: Atts -> Code-nameAlias att = comment- $$ (text "type"- <+> unknownNameAlias- <+> equals- <+> vtype Strng)+-- The Atts value isn't used; this is just to make it have the same+-- type as the other code-generating functions.+nameAlias :: Atts -> Code+nameAlias _ = cmnt+ $$ (text "type"+ <+> unknownNameAlias+ <+> equals+ <+> vtype Strng) where- comment = text "-- | The name for an" <+> unknownAttr- <> text "; must satisfy "- <+> quotes validUnknownName- <> text "."+ cmnt = text "-- | The name for an" <+> unknownAttr+ <> text "; must satisfy "+ <+> quotes validUnknownName+ <> text "." unknownNameAlias :: Code unknownNameAlias = text "AttributeName"@@ -191,7 +200,6 @@ hdr = text "instance" <+> text "PrintDot" <+> tpNm att <+> text "where" var = char 'v' sFunc = text "unqtDot"- cnct = text "<>" insts = asRows . (++ [unknownInst]) . map mkInstance@@ -227,17 +235,27 @@ $ atts att pFunc = text "parseUnqt" pType b a- | valtype a == Bl = pFld <> text "Bool" <+> cnst a- | isJust $ parseDef a = pFld <> text "Def" <+> cnst a <+> fromJust (parseDef a)- | otherwise = pFld <+> cnst a+ | valtype a == Bl = pFld <> text "Bool" <+> cnst a+ | isJust $ parseDef a = pFld <> text "Def" <+> cnst a <+> fromJust (parseDef a)+ | isJust $ emptyParse a = pFld <> text "NumDef" <+> cnst a <+> fromJust (emptyParse a)+ | otherwise = pFld <+> cnst a where pFld = text "parseField" <> if b then char 's' else empty parseAttr a = case map doubleQuotes $ parseNames a of [n] -> pType False a <+> n ns -> pType True a <+> docList ns- pUnknown = text "liftM2" <+> unknownAttr <+> text "stringBlock"- <+> parens (text "parseEq >> parse")+ unknownName = text "attrName"+ pUnknown = text "do"+ <+> ( (unknownName <+> text "<- stringBlock")+ $$ (text "liftEqParse'"+ <+> (parens (text "\"" <> unknownAttr <+> text "(\""+ <+> text "++ T.unpack" <+> unknownName+ <+> text "++ \")\"")+ $$ parens (unknownAttr <+> unknownName)+ )+ )+ ) arbitraryInstance :: Atts -> Code arbitraryInstance att = hdr $+$ fns@@ -448,168 +466,356 @@ -- The actual attributes --- ColorScheme is put earlier so that when sorting, it comes before the various *Color attributes.+-- Don't edit this value directly; edit the table below instead. attributes :: [Attribute]-attributes = [ makeAttr "Damping" ["Damping"] "G" Dbl Nothing (Just "0.99") (Just "@0.99@") (Just "@0.0@") (Just "neato only")- , makeAttr "K" ["K"] "GC" Dbl Nothing (Just "0.3") (Just "@0.3@") (Just "@0@") (Just "sfdp, fdp only")- , makeAttr "URL" ["URL", "href"] "ENGC" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, postscript, map only")- , makeAttr "ArrowHead" ["arrowhead"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing- , makeAttr "ArrowSize" ["arrowsize"] "E" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing- , makeAttr "ArrowTail" ["arrowtail"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing- , makeAttr "Aspect" ["aspect"] "G" (Cust "AspectType") Nothing Nothing Nothing Nothing (Just "dot only")- , makeAttr "BoundingBox" ["bb"] "G" (Cust "Rect") Nothing Nothing Nothing Nothing (Just "write only")- , makeAttr "ColorScheme" ["colorscheme"] "ENCG" (Cust "ColorScheme") Nothing (Just "X11") (Just "@'X11'@") Nothing Nothing- , makeAttr "BgColor" ["bgcolor"] "GC" (Cust "[Color]") Nothing (Just "[X11Color Transparent]") (Just "@['X11Color' 'Transparent']@") Nothing Nothing- , makeAttr "Center" ["center"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "Local") (Just "@'Local'@") Nothing (Just "dot only")- , makeAttr "Color" ["color"] "ENC" (Cust "[Color]") Nothing (Just "[X11Color Black]") (Just "@['X11Color' 'Black']@") Nothing Nothing- , makeAttr "Comment" ["comment"] "ENG" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing- , makeAttr "Compound" ["compound"] "G" Bl (Just "True") (Just "False")(Just "@'False'@") Nothing (Just "dot only")- , makeAttr "Concentrate" ["concentrate"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "Constraint" ["constraint"] "E" Bl (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "dot only")- , makeAttr "Decorate" ["decorate"] "E" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "DefaultDist" ["defaultdist"] "G" Dbl Nothing Nothing (Just "@1+(avg. len)*sqrt(|V|)@") (Just "@epsilon@") (Just "neato only, only if @'Pack' 'DontPack'@")- , makeAttr "Dim" ["dim"] "G" Integ Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only")- , makeAttr "Dimen" ["dimen"] "G" Integ Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only")- , makeAttr "Dir" ["dir"] "E" (Cust "DirType") Nothing Nothing (Just "@'Forward'@ (directed), @'NoDir'@ (undirected)") Nothing Nothing- , makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "NoConstraints") (Just "@'NoConstraints'@") Nothing (Just "neato only")- , makeAttr "Distortion" ["distortion"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing- , makeAttr "DPI" ["dpi", "resolution"] "G" Dbl Nothing Nothing (Just "@96.0@, @0.0@") Nothing (Just "svg, bitmap output only; \\\"resolution\\\" is a synonym")- , makeAttr "EdgeURL" ["edgeURL", "edgehref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")- , makeAttr "EdgeTarget" ["edgetarget"] "E" EStrng Nothing Nothing (Just "none") Nothing (Just "svg, map only")- , makeAttr "EdgeTooltip" ["edgetooltip"] "E" EStrng Nothing Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")- , makeAttr "Epsilon" ["epsilon"] "G" Dbl Nothing Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "neato only")- , makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "(DVal 3)") (Just "@'DVal' 3@") Nothing (Just "not dot")- , makeAttr "FillColor" ["fillcolor"] "NEC" (Cust "[Color]") Nothing (Just "[X11Color Black]")(Just "@['X11Color' 'LightGray']@ (nodes), @['X11Color' 'Black']@ (clusters)") Nothing Nothing- , makeAttr "FixedSize" ["fixedsize"] "N" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "FontColor" ["fontcolor"] "ENGC" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing- , makeAttr "FontName" ["fontname"] "ENGC" Strng Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing- , makeAttr "FontNames" ["fontnames"] "G" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only")- , makeAttr "FontPath" ["fontpath"] "G" Strng Nothing Nothing (Just "system dependent") Nothing Nothing- , makeAttr "FontSize" ["fontsize"] "ENGC" Dbl Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing- , makeAttr "ForceLabels" ["forcelabels"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "Only for 'XLabel' attributes, requires Graphviz >= 2.29.0")- , makeAttr "GradientAngle" ["gradientangle"] "NCG" Integ Nothing (Just "0") (Just "0") Nothing (Just "requires Graphviz >= 2.29.0")- , makeAttr "Group" ["group"] "N" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")- , makeAttr "HeadURL" ["headURL", "headhref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")- , makeAttr "HeadClip" ["headclip"] "E" Bl (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing- , makeAttr "HeadLabel" ["headlabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing- , makeAttr "HeadPort" ["headport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing- , makeAttr "HeadTarget" ["headtarget"] "E" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")- , makeAttr "HeadTooltip" ["headtooltip"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")- , makeAttr "Height" ["height"] "N" Dbl Nothing (Just "0.5") (Just "@0.5@") (Just "@0.02@") Nothing- , makeAttr "ID" ["id"] "GNE" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"") Nothing (Just "svg, postscript, map only")- , makeAttr "Image" ["image"] "N" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing- , makeAttr "ImagePath" ["imagepath"] "G" (Cust "Paths") Nothing (Just "(Paths [])") (Just "@'Paths' []@") Nothing (Just "Printing and parsing is OS-specific, requires Graphviz >= 2.29.0")- , makeAttr "ImageScale" ["imagescale"] "N" (Cust "ScaleType") (Just "UniformScale") (Just "NoScale") (Just "@'NoScale'@") Nothing Nothing- , makeAttr "Label" ["label"] "ENGC" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)") Nothing Nothing- , makeAttr "LabelURL" ["labelURL", "labelhref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")- , makeAttr "LabelScheme" ["label_scheme"] "G" (Cust "LabelScheme") Nothing (Just "NotEdgeLabel") (Just "@'NotEdgeLabel'@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0")- , makeAttr "LabelAngle" ["labelangle"] "E" Dbl Nothing (Just "(-25)") (Just "@-25.0@") (Just "@-180.0@") Nothing- , makeAttr "LabelDistance" ["labeldistance"] "E" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing- , makeAttr "LabelFloat" ["labelfloat"] "E" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "LabelFontColor" ["labelfontcolor"] "E" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing- , makeAttr "LabelFontName" ["labelfontname"] "E" Strng Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing- , makeAttr "LabelFontSize" ["labelfontsize"] "E" Dbl Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing- , makeAttr "LabelJust" ["labeljust"] "GC" (Cust "Justification") Nothing (Just "JCenter") (Just "@'JCenter'@") Nothing Nothing- , makeAttr "LabelLoc" ["labelloc"] "GCN" (Cust "VerticalPlacement") Nothing (Just "VTop") (Just "@'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)") Nothing Nothing- , makeAttr "LabelTarget" ["labeltarget"] "E" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")- , makeAttr "LabelTooltip" ["labeltooltip"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")- , makeAttr "Landscape" ["landscape"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "Layer" ["layer"] "EN" (Cust "LayerRange") Nothing Nothing Nothing Nothing Nothing- , makeAttr "Layers" ["layers"] "G" (Cust "LayerList") Nothing (Just "(LL [])") (Just "@'LL' []@") Nothing Nothing- , makeAttr "LayerSep" ["layersep"] "G" (Cust "LayerSep") Nothing (Just "(LSep \" :\\t\")") (Just "@'LSep' \\\" :\\t\\\"@") Nothing Nothing- , makeAttr "Layout" ["layout"] "G" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing- , makeAttr "Len" ["len"] "E" Dbl Nothing Nothing (Just "@1.0@ (neato), @0.3@ (fdp)") Nothing (Just "fdp, neato only")- , makeAttr "LevelsGap" ["levelsgap"] "G" Dbl Nothing (Just "0") (Just "@0.0@") Nothing (Just "neato only")- , makeAttr "Levels" ["levels"] "G" Integ Nothing (Just "maxBound") (Just "@'maxBound'@") (Just "@0@") (Just "sfdp only")- , makeAttr "LHead" ["lhead"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")- , makeAttr "LHeight" ["LHeight"] "GC" Dbl Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0")- , makeAttr "LPos" ["lp"] "EGC" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only")- , makeAttr "LTail" ["ltail"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")- , makeAttr "LWidth" ["lwidth"] "GC" Dbl Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0")- , makeAttr "Margin" ["margin"] "NG" (Cust "DPoint") Nothing Nothing (Just "device dependent") Nothing Nothing- , makeAttr "MaxIter" ["maxiter"] "G" Integ Nothing Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp)") Nothing (Just "fdp, neato only")- , makeAttr "MCLimit" ["mclimit"] "G" Dbl Nothing (Just "1") (Just "@1.0@") Nothing (Just "dot only")- , makeAttr "MinDist" ["mindist"] "G" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "circo only")- , makeAttr "MinLen" ["minlen"] "E" Integ Nothing (Just "1") (Just "@1@") (Just "@0@") (Just "dot only")- , makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "Major") (Just "@'Major'@") Nothing (Just "neato only")- , makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "ShortPath") (Just "@'ShortPath'@") Nothing (Just "neato only")- , makeAttr "Mosek" ["mosek"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "neato only; requires the Mosek software")- , makeAttr "NodeSep" ["nodesep"] "G" Dbl Nothing (Just "0.25") (Just "@0.25@") (Just "@0.02@") (Just "dot only")- , makeAttr "NoJustify" ["nojustify"] "GCNE" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "Normalize" ["normalize"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "not dot")- , makeAttr "Nslimit" ["nslimit"] "G" Dbl Nothing Nothing Nothing Nothing (Just "dot only")- , makeAttr "Nslimit1" ["nslimit1"] "G" Dbl Nothing Nothing Nothing Nothing (Just "dot only")- , makeAttr "Ordering" ["ordering"] "GN" (Cust "Order") Nothing Nothing (Just "none") Nothing (Just "dot only")- , makeAttr "Orientation" ["orientation"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@360.0@") Nothing- , makeAttr "OutputOrder" ["outputorder"] "G" (Cust "OutputMode") Nothing (Just "BreadthFirst") (Just "@'BreadthFirst'@") Nothing Nothing- , makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not dot")- , makeAttr "OverlapScaling" ["overlap_scaling"] "G" Dbl Nothing (Just "(-4)") (Just "@-4@") (Just "@-1.0e10@") (Just "prism only")- , makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "DontPack") (Just "@'DontPack'@") Nothing (Just "not dot")- , makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "PackNode") (Just "@'PackNode'@") Nothing (Just "not dot")- , makeAttr "Pad" ["pad"] "G" (Cust "DPoint") Nothing (Just "(DVal 0.0555)") (Just "@'DVal' 0.0555@ (4 points)") Nothing Nothing- , makeAttr "Page" ["page"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing- , makeAttr "PageDir" ["pagedir"] "G" (Cust "PageDir") Nothing (Just "Bl") (Just "@'Bl'@") Nothing Nothing- , makeAttr "PenColor" ["pencolor"] "C" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing- , makeAttr "PenWidth" ["penwidth"] "CNE" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing- , makeAttr "Peripheries" ["peripheries"] "NC" Integ Nothing (Just "1") (Just "shape default (nodes), @1@ (clusters)") (Just "0") Nothing- , makeAttr "Pin" ["pin"] "N" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "fdp, neato only")- , makeAttr "Pos" ["pos"] "EN" (Cust "Pos") Nothing Nothing Nothing Nothing Nothing- , makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "sfdp only")- , makeAttr "Quantum" ["quantum"] "G" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@0.0@") Nothing- , makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing Nothing (Just "dot only")- , makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "FromTop") (Just "@'FromTop'@") Nothing (Just "dot only")- , makeAttr "RankSep" ["ranksep"] "G" (Cust "[Double]") Nothing Nothing (Just "@[0.5]@ (dot), @[1.0]@ (twopi)") (Just "[0.02]") (Just "twopi, dot only")- , makeAttr "Ratio" ["ratio"] "G" (Cust "Ratios") Nothing Nothing Nothing Nothing Nothing- , makeAttr "Rects" ["rects"] "N" (Cust "[Rect]") Nothing Nothing Nothing Nothing (Just "write only")- , makeAttr "Regular" ["regular"] "N" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing- , makeAttr "ReMinCross" ["remincross"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only")- , makeAttr "RepulsiveForce" ["repulsiveforce"] "G" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "sfdp only")- , makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "(NodeName \"\")") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "circo, twopi only")- , makeAttr "Rotate" ["rotate"] "G" Integ Nothing (Just "0") (Just "@0@") Nothing Nothing- , makeAttr "Rotation" ["rotation"] "G" Dbl Nothing (Just "0") (Just "@0@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0")- , makeAttr "SameHead" ["samehead"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")- , makeAttr "SameTail" ["sametail"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")- , makeAttr "SamplePoints" ["samplepoints"] "N" Integ Nothing Nothing (Just "@8@ (output), @20@ (overlap and image maps)") Nothing Nothing- , makeAttr "Scale" ["scale"] "G" (Cust "DPoint") Nothing Nothing Nothing Nothing (Just "twopi only, requires Graphviz >= 2.28.0")- , makeAttr "SearchSize" ["searchsize"] "G" Integ Nothing (Just "30") (Just "@30@") Nothing (Just "dot only")- , makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "(DVal 4)") (Just "@'DVal' 4@") Nothing (Just "not dot")- , makeAttr "Shape" ["shape"] "N" (Cust "Shape") Nothing (Just "Ellipse") (Just "@'Ellipse'@") Nothing Nothing- , makeAttr "ShapeFile" ["shapefile"] "N" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing- , makeAttr "ShowBoxes" ["showboxes"] "ENG" Integ Nothing (Just "0") (Just "@0@") (Just "@0@") (Just "dot only")- , makeAttr "Sides" ["sides"] "N" Integ Nothing (Just "4") (Just "@4@") (Just "@0@") Nothing- , makeAttr "Size" ["size"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing- , makeAttr "Skew" ["skew"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing- , makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "NoSmooth") (Just "@'NoSmooth'@") Nothing (Just "sfdp only")- , makeAttr "SortV" ["sortv"] "GCN" (Cust "Word16") Nothing (Just "0") (Just "@0@") (Just "@0@") Nothing- , makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") (Just "SplineEdges") Nothing Nothing Nothing- , makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing Nothing Nothing Nothing (Just "fdp, neato only")- , makeAttr "Style" ["style"] "ENC" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing Nothing- , makeAttr "StyleSheet" ["stylesheet"] "G" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only")- , makeAttr "TailURL" ["tailURL", "tailhref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")- , makeAttr "TailClip" ["tailclip"] "E" Bl (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing- , makeAttr "TailLabel" ["taillabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing- , makeAttr "TailPort" ["tailport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing- , makeAttr "TailTarget" ["tailtarget"] "E" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")- , makeAttr "TailTooltip" ["tailtooltip"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")- , makeAttr "Target" ["target"] "ENGC" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")- , makeAttr "Tooltip" ["tooltip"] "NEC" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")- , makeAttr "TrueColor" ["truecolor"] "G" Bl (Just "True") Nothing Nothing Nothing (Just "bitmap output only")- , makeAttr "Vertices" ["vertices"] "N" (Cust "[Point]") Nothing Nothing Nothing Nothing (Just "write only")- , makeAttr "ViewPort" ["viewport"] "G" (Cust "ViewPort") Nothing Nothing (Just "none") Nothing Nothing- , makeAttr "VoroMargin" ["voro_margin"] "G" Dbl Nothing (Just "0.05") (Just "@0.05@") (Just "@0.0@") (Just "not dot")- , makeAttr "Weight" ["weight"] "E" Dbl Nothing Nothing (Just "@1.0@") (Just "@0@ (dot), @1@ (neato,fdp,sfdp)") Nothing- , makeAttr "Width" ["width"] "N" Dbl Nothing (Just "0.75") (Just "@0.75@") (Just "@0.01@") Nothing- , makeAttr "XLabel" ["xlabel"] "EN" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing (Just "requires Graphviz >= 2.29.0")- , makeAttr "Z" ["z"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@-MAXFLOAT@, @-1000@") Nothing- ]+attributes = [+ -- BEGIN RECEIVE ORGTBL Attributes+ makeAttr "Damping" ["Damping"] "G" (Dbl) Nothing (Just "0.99") (Just "@0.99@") (Just "@0.0@") (Just "neato only"),+ makeAttr "K" ["K"] "GC" (Dbl) Nothing (Just "0.3") (Just "@0.3@") (Just "@0@") (Just "sfdp, fdp only"),+ makeAttr "URL" ["URL", "href"] "ENGC" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, postscript, map only"),+ makeAttr "ArrowHead" ["arrowhead"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing,+ makeAttr "ArrowSize" ["arrowsize"] "E" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing,+ makeAttr "ArrowTail" ["arrowtail"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing,+ makeAttr "Aspect" ["aspect"] "G" (Cust "AspectType") Nothing Nothing Nothing Nothing (Just "dot only"),+ makeAttr "BoundingBox" ["bb"] "G" (Cust "Rect") Nothing Nothing Nothing Nothing (Just "write only"),+ makeAttr "ColorScheme" ["colorscheme"] "ENCG" (Cust "ColorScheme") Nothing (Just "X11") (Just "@'X11'@") Nothing Nothing,+ makeAttr "BgColor" ["bgcolor"] "GC" (Cust "[Color]") Nothing (Just "[X11Color Transparent]") (Just "@['X11Color' 'Transparent']@") Nothing Nothing,+ makeAttr "Center" ["center"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "Local") (Just "@'Local'@") Nothing (Just "dot only"),+ makeAttr "Color" ["color"] "ENC" (Cust "[Color]") Nothing (Just "[X11Color Black]") (Just "@['X11Color' 'Black']@") Nothing Nothing,+ makeAttr "Comment" ["comment"] "ENG" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,+ makeAttr "Compound" ["compound"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only"),+ makeAttr "Concentrate" ["concentrate"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "Constraint" ["constraint"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "dot only"),+ makeAttr "Decorate" ["decorate"] "E" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "DefaultDist" ["defaultdist"] "G" (Dbl) Nothing Nothing (Just "@1+(avg. len)*sqrt(abs(V))@") (Just "@epsilon@") (Just "neato only, only if @'Pack' 'DontPack'@"),+ makeAttr "Dim" ["dim"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only"),+ makeAttr "Dimen" ["dimen"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only"),+ makeAttr "Dir" ["dir"] "E" (Cust "DirType") Nothing Nothing (Just "@'Forward'@ (directed), @'NoDir'@ (undirected)") Nothing Nothing,+ makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "NoConstraints") (Just "@'NoConstraints'@") Nothing (Just "neato only"),+ makeAttr "Distortion" ["distortion"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing,+ makeAttr "DPI" ["dpi", "resolution"] "G" (Dbl) Nothing Nothing (Just "@96.0@, @0.0@") Nothing (Just "svg, bitmap output only; \\\"resolution\\\" is a synonym"),+ makeAttr "EdgeURL" ["edgeURL", "edgehref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),+ makeAttr "EdgeTarget" ["edgetarget"] "E" (EStrng) Nothing Nothing (Just "none") Nothing (Just "svg, map only"),+ makeAttr "EdgeTooltip" ["edgetooltip"] "E" (EStrng) Nothing Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),+ makeAttr "Epsilon" ["epsilon"] "G" (Dbl) Nothing Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "neato only"),+ makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "(DVal 3)") (Just "@'DVal' 3@") Nothing (Just "not dot"),+ makeAttr "FillColor" ["fillcolor"] "NEC" (Cust "[Color]") Nothing (Just "[X11Color Black]") (Just "@['X11Color' 'LightGray']@ (nodes), @['X11Color' 'Black']@ (clusters)") Nothing Nothing,+ makeAttr "FixedSize" ["fixedsize"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "FontColor" ["fontcolor"] "ENGC" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing,+ makeAttr "FontName" ["fontname"] "ENGC" (Strng) Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing,+ makeAttr "FontNames" ["fontnames"] "G" (Cust "SVGFontNames") Nothing (Just "SvgNames") (Just "@'SvgNames'@") Nothing (Just "svg only"),+ makeAttr "FontPath" ["fontpath"] "G" (Strng) Nothing Nothing (Just "system dependent") Nothing Nothing,+ makeAttr "FontSize" ["fontsize"] "ENGC" (Dbl) Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing,+ makeAttr "ForceLabels" ["forcelabels"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "Only for 'XLabel' attributes, requires Graphviz >= 2.29.0"),+ makeAttr "GradientAngle" ["gradientangle"] "NCG" (Integ) Nothing (Just "0") (Just "0") Nothing (Just "requires Graphviz >= 2.29.0"),+ makeAttr "Group" ["group"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "HeadURL" ["headURL", "headhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),+ makeAttr "HeadClip" ["headclip"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing,+ makeAttr "HeadLabel" ["headlabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing,+ makeAttr "HeadPort" ["headport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing,+ makeAttr "HeadTarget" ["headtarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),+ makeAttr "HeadTooltip" ["headtooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),+ makeAttr "Height" ["height"] "N" (Dbl) Nothing (Just "0.5") (Just "@0.5@") (Just "@0.02@") Nothing,+ makeAttr "ID" ["id"] "GNE" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, postscript, map only"),+ makeAttr "Image" ["image"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,+ makeAttr "ImagePath" ["imagepath"] "G" (Cust "Paths") Nothing (Just "(Paths [])") (Just "@'Paths' []@") Nothing (Just "Printing and parsing is OS-specific, requires Graphviz >= 2.29.0"),+ makeAttr "ImageScale" ["imagescale"] "N" (Cust "ScaleType") (Just "UniformScale") (Just "NoScale") (Just "@'NoScale'@") Nothing Nothing,+ makeAttr "Label" ["label"] "ENGC" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)") Nothing Nothing,+ makeAttr "LabelURL" ["labelURL", "labelhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),+ makeAttr "LabelScheme" ["label_scheme"] "G" (Cust "LabelScheme") Nothing (Just "NotEdgeLabel") (Just "@'NotEdgeLabel'@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0"),+ makeAttr "LabelAngle" ["labelangle"] "E" (Dbl) Nothing (Just "(-25)") (Just "@-25.0@") (Just "@-180.0@") Nothing,+ makeAttr "LabelDistance" ["labeldistance"] "E" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing,+ makeAttr "LabelFloat" ["labelfloat"] "E" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "LabelFontColor" ["labelfontcolor"] "E" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing,+ makeAttr "LabelFontName" ["labelfontname"] "E" (Strng) Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing,+ makeAttr "LabelFontSize" ["labelfontsize"] "E" (Dbl) Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing,+ makeAttr "LabelJust" ["labeljust"] "GC" (Cust "Justification") Nothing (Just "JCenter") (Just "@'JCenter'@") Nothing Nothing,+ makeAttr "LabelLoc" ["labelloc"] "GCN" (Cust "VerticalPlacement") Nothing (Just "VTop") (Just "@'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)") Nothing Nothing,+ makeAttr "LabelTarget" ["labeltarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),+ makeAttr "LabelTooltip" ["labeltooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),+ makeAttr "Landscape" ["landscape"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "Layer" ["layer"] "EN" (Cust "LayerRange") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "Layers" ["layers"] "G" (Cust "LayerList") Nothing (Just "(LL [])") (Just "@'LL' []@") Nothing Nothing,+ makeAttr "LayerSep" ["layersep"] "G" (Cust "LayerSep") Nothing (Just "(LSep \" :\\t\")") (Just "@'LSep' \\\" :\\t\\\"@") Nothing Nothing,+ makeAttr "Layout" ["layout"] "G" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,+ makeAttr "Len" ["len"] "E" (Dbl) Nothing Nothing (Just "@1.0@ (neato), @0.3@ (fdp)") Nothing (Just "fdp, neato only"),+ makeAttr "LevelsGap" ["levelsgap"] "G" (Dbl) Nothing (Just "0") (Just "@0.0@") Nothing (Just "neato only"),+ makeAttr "Levels" ["levels"] "G" (Integ) Nothing (Just "maxBound") (Just "@'maxBound'@") (Just "@0@") (Just "sfdp only"),+ makeAttr "LHead" ["lhead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "LHeight" ["LHeight"] "GC" (Dbl) Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0"),+ makeAttr "LPos" ["lp"] "EGC" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only"),+ makeAttr "LTail" ["ltail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "LWidth" ["lwidth"] "GC" (Dbl) Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0"),+ makeAttr "Margin" ["margin"] "NG" (Cust "DPoint") Nothing Nothing (Just "device dependent") Nothing Nothing,+ makeAttr "MaxIter" ["maxiter"] "G" (Integ) Nothing Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp)") Nothing (Just "fdp, neato only"),+ makeAttr "MCLimit" ["mclimit"] "G" (Dbl) Nothing (Just "1") (Just "@1.0@") Nothing (Just "dot only"),+ makeAttr "MinDist" ["mindist"] "G" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "circo only"),+ makeAttr "MinLen" ["minlen"] "E" (Integ) Nothing (Just "1") (Just "@1@") (Just "@0@") (Just "dot only"),+ makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "Major") (Just "@'Major'@") Nothing (Just "neato only"),+ makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "ShortPath") (Just "@'ShortPath'@") Nothing (Just "neato only"),+ makeAttr "Mosek" ["mosek"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "neato only; requires the Mosek software"),+ makeAttr "NodeSep" ["nodesep"] "G" (Dbl) Nothing (Just "0.25") (Just "@0.25@") (Just "@0.02@") (Just "dot only"),+ makeAttr "NoJustify" ["nojustify"] "GCNE" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "Normalize" ["normalize"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "not dot"),+ makeAttr "Nslimit" ["nslimit"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "dot only"),+ makeAttr "Nslimit1" ["nslimit1"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "dot only"),+ makeAttr "Ordering" ["ordering"] "GN" (Cust "Order") Nothing Nothing (Just "none") Nothing (Just "dot only"),+ makeAttr "Orientation" ["orientation"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@360.0@") Nothing,+ makeAttr "OutputOrder" ["outputorder"] "G" (Cust "OutputMode") Nothing (Just "BreadthFirst") (Just "@'BreadthFirst'@") Nothing Nothing,+ makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not dot"),+ makeAttr "OverlapScaling" ["overlap_scaling"] "G" (Dbl) Nothing (Just "(-4)") (Just "@-4@") (Just "@-1.0e10@") (Just "prism only"),+ makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "DontPack") (Just "@'DontPack'@") Nothing (Just "not dot"),+ makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "PackNode") (Just "@'PackNode'@") Nothing (Just "not dot"),+ makeAttr "Pad" ["pad"] "G" (Cust "DPoint") Nothing (Just "(DVal 0.0555)") (Just "@'DVal' 0.0555@ (4 points)") Nothing Nothing,+ makeAttr "Page" ["page"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "PageDir" ["pagedir"] "G" (Cust "PageDir") Nothing (Just "Bl") (Just "@'Bl'@") Nothing Nothing,+ makeAttr "PenColor" ["pencolor"] "C" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing,+ makeAttr "PenWidth" ["penwidth"] "CNE" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing,+ makeAttr "Peripheries" ["peripheries"] "NC" (Integ) Nothing (Just "1") (Just "shape default (nodes), @1@ (clusters)") (Just "0") Nothing,+ makeAttr "Pin" ["pin"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "fdp, neato only"),+ makeAttr "Pos" ["pos"] "EN" (Cust "Pos") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "sfdp only"),+ makeAttr "Quantum" ["quantum"] "G" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@0.0@") Nothing,+ makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing Nothing (Just "dot only"),+ makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "FromTop") (Just "@'FromTop'@") Nothing (Just "dot only"),+ makeAttr "RankSep" ["ranksep"] "G" (Cust "[Double]") Nothing Nothing (Just "@[0.5]@ (dot), @[1.0]@ (twopi)") (Just "[0.02]") (Just "twopi, dot only"),+ makeAttr "Ratio" ["ratio"] "G" (Cust "Ratios") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "Rects" ["rects"] "N" (Cust "[Rect]") Nothing Nothing Nothing Nothing (Just "write only"),+ makeAttr "Regular" ["regular"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,+ makeAttr "ReMinCross" ["remincross"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only"),+ makeAttr "RepulsiveForce" ["repulsiveforce"] "G" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "sfdp only"),+ makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "(NodeName \"\")") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "circo, twopi only"),+ makeAttr "Rotate" ["rotate"] "G" (Integ) Nothing (Just "0") (Just "@0@") Nothing Nothing,+ makeAttr "Rotation" ["rotation"] "G" (Dbl) Nothing (Just "0") (Just "@0@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0"),+ makeAttr "SameHead" ["samehead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "SameTail" ["sametail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),+ makeAttr "SamplePoints" ["samplepoints"] "N" (Integ) Nothing Nothing (Just "@8@ (output), @20@ (overlap and image maps)") Nothing Nothing,+ makeAttr "Scale" ["scale"] "G" (Cust "DPoint") Nothing Nothing Nothing Nothing (Just "twopi only, requires Graphviz >= 2.28.0"),+ makeAttr "SearchSize" ["searchsize"] "G" (Integ) Nothing (Just "30") (Just "@30@") Nothing (Just "dot only"),+ makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "(DVal 4)") (Just "@'DVal' 4@") Nothing (Just "not dot"),+ makeAttr "Shape" ["shape"] "N" (Cust "Shape") Nothing (Just "Ellipse") (Just "@'Ellipse'@") Nothing Nothing,+ makeAttr "ShapeFile" ["shapefile"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,+ makeAttr "ShowBoxes" ["showboxes"] "ENG" (Integ) Nothing (Just "0") (Just "@0@") (Just "@0@") (Just "dot only"),+ makeAttr "Sides" ["sides"] "N" (Integ) Nothing (Just "4") (Just "@4@") (Just "@0@") Nothing,+ makeAttr "Size" ["size"] "G" (Cust "GraphSize") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "Skew" ["skew"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing,+ makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "NoSmooth") (Just "@'NoSmooth'@") Nothing (Just "sfdp only"),+ makeAttr "SortV" ["sortv"] "GCN" (Cust "Word16") Nothing (Just "0") (Just "@0@") (Just "@0@") Nothing,+ makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") (Just "SplineEdges") Nothing Nothing Nothing,+ makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing Nothing Nothing Nothing (Just "fdp, neato only"),+ makeAttr "Style" ["style"] "ENC" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing Nothing,+ makeAttr "StyleSheet" ["stylesheet"] "G" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only"),+ makeAttr "TailURL" ["tailURL", "tailhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),+ makeAttr "TailClip" ["tailclip"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing,+ makeAttr "TailLabel" ["taillabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing,+ makeAttr "TailPort" ["tailport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing,+ makeAttr "TailTarget" ["tailtarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),+ makeAttr "TailTooltip" ["tailtooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),+ makeAttr "Target" ["target"] "ENGC" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),+ makeAttr "Tooltip" ["tooltip"] "NEC" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),+ makeAttr "TrueColor" ["truecolor"] "G" (Bl) (Just "True") Nothing Nothing Nothing (Just "bitmap output only"),+ makeAttr "Vertices" ["vertices"] "N" (Cust "[Point]") Nothing Nothing Nothing Nothing (Just "write only"),+ makeAttr "ViewPort" ["viewport"] "G" (Cust "ViewPort") Nothing Nothing (Just "none") Nothing Nothing,+ makeAttr "VoroMargin" ["voro_margin"] "G" (Dbl) Nothing (Just "0.05") (Just "@0.05@") (Just "@0.0@") (Just "not dot"),+ makeAttr "Weight" ["weight"] "E" (Dbl) Nothing Nothing (Just "@1.0@") (Just "@0@ (dot), @1@ (neato,fdp,sfdp)") Nothing,+ makeAttr "Width" ["width"] "N" (Dbl) Nothing (Just "0.75") (Just "@0.75@") (Just "@0.01@") Nothing,+ makeAttr "XLabel" ["xlabel"] "EN" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing (Just "requires Graphviz >= 2.29.0"),+ makeAttr "Z" ["z"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@-MAXFLOAT@, @-1000@") Nothing+ -- END RECEIVE ORGTBL Attributes+ ] +{-++When using Emacs with org-mode available, hitting ` C-c C-c ' inside+the table below should update the actual Haskell code above.++This way, you can more easily edit/update the appropriate values.++* Values in "Allowed names" should be space-separated (and are+ converted into a list of Strings).++* Used by should consist of a sub-set of `ENGCS'.++* The entries in "Type" should be a valid Haskell value of type+ 'VType' (parens are added).++* An empty cell in the last five columns translates to a `Nothing'+ value; anything else is wrapped in quotes and then has Just applied to+ it. As such, you still need to escape quotes.++* Any entries in 'Parsing default' or "Default value" should be a+ valid Haskell value (add parens if needed) with the exception that+ double-quotes should be escaped.++#+ORGTBL: SEND Attributes orgtbl-to-generic :skip 2 :splice t :hline nil :no-escape t :lstart " makeAttr " :lend "," :llend "" :sep " " :fmt (1 cell-quote 2 cell-to-list 3 cell-quote 4 cell-parens 5 cell-to-maybe 6 cell-to-maybe 7 cell-to-maybe 8 cell-to-maybe 9 cell-to-maybe)+| Constructor | Allowed names | Used By | Type | Parsing default | Default value | Default for Documentation | Minimum | Comment notes |+|--------------------+--------------------+---------+--------------------------+-----------------+----------------------------+--------------------------------------------------------------------------+---------------------------------+------------------------------------------------------------------|+| Damping | Damping | G | Dbl | | 0.99 | @0.99@ | @0.0@ | neato only |+| K | K | GC | Dbl | | 0.3 | @0.3@ | @0@ | sfdp, fdp only |+| URL | URL href | ENGC | EStrng | | \"\" | none | | svg, postscript, map only |+| ArrowHead | arrowhead | E | Cust "ArrowType" | | normal | @'normal'@ | | |+| ArrowSize | arrowsize | E | Dbl | | 1 | @1.0@ | @0.0@ | |+| ArrowTail | arrowtail | E | Cust "ArrowType" | | normal | @'normal'@ | | |+| Aspect | aspect | G | Cust "AspectType" | | | | | dot only |+| BoundingBox | bb | G | Cust "Rect" | | | | | write only |+| ColorScheme | colorscheme | ENCG | Cust "ColorScheme" | | X11 | @'X11'@ | | |+| BgColor | bgcolor | GC | Cust "[Color]" | | [X11Color Transparent] | @['X11Color' 'Transparent']@ | | |+| Center | center | G | Bl | True | False | @'False'@ | | |+| ClusterRank | clusterrank | G | Cust "ClusterMode" | | Local | @'Local'@ | | dot only |+| Color | color | ENC | Cust "[Color]" | | [X11Color Black] | @['X11Color' 'Black']@ | | |+| Comment | comment | ENG | Strng | | \"\" | @\\\"\\\"@ | | |+| Compound | compound | G | Bl | True | False | @'False'@ | | dot only |+| Concentrate | concentrate | G | Bl | True | False | @'False'@ | | |+| Constraint | constraint | E | Bl | True | True | @'True'@ | | dot only |+| Decorate | decorate | E | Bl | True | False | @'False'@ | | |+| DefaultDist | defaultdist | G | Dbl | | | @1+(avg. len)*sqrt(abs(V))@ | @epsilon@ | neato only, only if @'Pack' 'DontPack'@ |+| Dim | dim | G | Integ | | 2 | @2@ | @2@ | sfdp, fdp, neato only |+| Dimen | dimen | G | Integ | | 2 | @2@ | @2@ | sfdp, fdp, neato only |+| Dir | dir | E | Cust "DirType" | | | @'Forward'@ (directed), @'NoDir'@ (undirected) | | |+| DirEdgeConstraints | diredgeconstraints | G | Cust "DEConstraints" | EdgeConstraints | NoConstraints | @'NoConstraints'@ | | neato only |+| Distortion | distortion | N | Dbl | | 0 | @0.0@ | @-100.0@ | |+| DPI | dpi resolution | G | Dbl | | | @96.0@, @0.0@ | | svg, bitmap output only; \\\"resolution\\\" is a synonym |+| EdgeURL | edgeURL edgehref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| EdgeTarget | edgetarget | E | EStrng | | | none | | svg, map only |+| EdgeTooltip | edgetooltip | E | EStrng | | | @\\\"\\\"@ | | svg, cmap only |+| Epsilon | epsilon | G | Dbl | | | @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@) | | neato only |+| ESep | esep | G | Cust "DPoint" | | (DVal 3) | @'DVal' 3@ | | not dot |+| FillColor | fillcolor | NEC | Cust "[Color]" | | [X11Color Black] | @['X11Color' 'LightGray']@ (nodes), @['X11Color' 'Black']@ (clusters) | | |+| FixedSize | fixedsize | N | Bl | True | False | @'False'@ | | |+| FontColor | fontcolor | ENGC | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |+| FontName | fontname | ENGC | Strng | | \"Times-Roman\" | @\\\"Times-Roman\\\"@ | | |+| FontNames | fontnames | G | Cust "SVGFontNames" | | SvgNames | @'SvgNames'@ | | svg only |+| FontPath | fontpath | G | Strng | | | system dependent | | |+| FontSize | fontsize | ENGC | Dbl | | 14 | @14.0@ | @1.0@ | |+| ForceLabels | forcelabels | G | Bl | True | False | @'False'@ | | Only for 'XLabel' attributes, requires Graphviz >= 2.29.0 |+| GradientAngle | gradientangle | NCG | Integ | | 0 | 0 | | requires Graphviz >= 2.29.0 |+| Group | group | N | Strng | | \"\" | @\\\"\\\"@ | | dot only |+| HeadURL | headURL headhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| HeadClip | headclip | E | Bl | True | True | @'True'@ | | |+| HeadLabel | headlabel | E | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | |+| HeadPort | headport | E | Cust "PortPos" | | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@ | | |+| HeadTarget | headtarget | E | EStrng | | \"\" | none | | svg, map only |+| HeadTooltip | headtooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Height | height | N | Dbl | | 0.5 | @0.5@ | @0.02@ | |+| ID | id | GNE | EStrng | | \"\" | @\\\"\\\"@ | | svg, postscript, map only |+| Image | image | N | Strng | | \"\" | @\\\"\\\"@ | | |+| ImagePath | imagepath | G | Cust "Paths" | | (Paths []) | @'Paths' []@ | | Printing and parsing is OS-specific, requires Graphviz >= 2.29.0 |+| ImageScale | imagescale | N | Cust "ScaleType" | UniformScale | NoScale | @'NoScale'@ | | |+| Label | label | ENGC | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise) | | |+| LabelURL | labelURL labelhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| LabelScheme | label_scheme | G | Cust "LabelScheme" | | NotEdgeLabel | @'NotEdgeLabel'@ | | sfdp only, requires Graphviz >= 2.28.0 |+| LabelAngle | labelangle | E | Dbl | | (-25) | @-25.0@ | @-180.0@ | |+| LabelDistance | labeldistance | E | Dbl | | 1 | @1.0@ | @0.0@ | |+| LabelFloat | labelfloat | E | Bl | True | False | @'False'@ | | |+| LabelFontColor | labelfontcolor | E | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |+| LabelFontName | labelfontname | E | Strng | | \"Times-Roman\" | @\\\"Times-Roman\\\"@ | | |+| LabelFontSize | labelfontsize | E | Dbl | | 14 | @14.0@ | @1.0@ | |+| LabelJust | labeljust | GC | Cust "Justification" | | JCenter | @'JCenter'@ | | |+| LabelLoc | labelloc | GCN | Cust "VerticalPlacement" | | VTop | @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes) | | |+| LabelTarget | labeltarget | E | EStrng | | \"\" | none | | svg, map only |+| LabelTooltip | labeltooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Landscape | landscape | G | Bl | True | False | @'False'@ | | |+| Layer | layer | EN | Cust "LayerRange" | | | | | |+| Layers | layers | G | Cust "LayerList" | | (LL []) | @'LL' []@ | | |+| LayerSep | layersep | G | Cust "LayerSep" | | (LSep \" :\\t\") | @'LSep' \\\" :\\t\\\"@ | | |+| Layout | layout | G | Strng | | \"\" | @\\\"\\\"@ | | |+| Len | len | E | Dbl | | | @1.0@ (neato), @0.3@ (fdp) | | fdp, neato only |+| LevelsGap | levelsgap | G | Dbl | | 0 | @0.0@ | | neato only |+| Levels | levels | G | Integ | | maxBound | @'maxBound'@ | @0@ | sfdp only |+| LHead | lhead | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |+| LHeight | LHeight | GC | Dbl | | | | | write only, requires Graphviz >= 2.28.0 |+| LPos | lp | EGC | Cust "Point" | | | | | write only |+| LTail | ltail | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |+| LWidth | lwidth | GC | Dbl | | | | | write only, requires Graphviz >= 2.28.0 |+| Margin | margin | NG | Cust "DPoint" | | | device dependent | | |+| MaxIter | maxiter | G | Integ | | | @100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp) | | fdp, neato only |+| MCLimit | mclimit | G | Dbl | | 1 | @1.0@ | | dot only |+| MinDist | mindist | G | Dbl | | 1 | @1.0@ | @0.0@ | circo only |+| MinLen | minlen | E | Integ | | 1 | @1@ | @0@ | dot only |+| Mode | mode | G | Cust "ModeType" | | Major | @'Major'@ | | neato only |+| Model | model | G | Cust "Model" | | ShortPath | @'ShortPath'@ | | neato only |+| Mosek | mosek | G | Bl | True | False | @'False'@ | | neato only; requires the Mosek software |+| NodeSep | nodesep | G | Dbl | | 0.25 | @0.25@ | @0.02@ | dot only |+| NoJustify | nojustify | GCNE | Bl | True | False | @'False'@ | | |+| Normalize | normalize | G | Bl | True | False | @'False'@ | | not dot |+| Nslimit | nslimit | G | Dbl | | | | | dot only |+| Nslimit1 | nslimit1 | G | Dbl | | | | | dot only |+| Ordering | ordering | GN | Cust "Order" | | | none | | dot only |+| Orientation | orientation | N | Dbl | | 0 | @0.0@ | @360.0@ | |+| OutputOrder | outputorder | G | Cust "OutputMode" | | BreadthFirst | @'BreadthFirst'@ | | |+| Overlap | overlap | G | Cust "Overlap" | KeepOverlaps | KeepOverlaps | @'KeepOverlaps'@ | | not dot |+| OverlapScaling | overlap_scaling | G | Dbl | | (-4) | @-4@ | @-1.0e10@ | prism only |+| Pack | pack | G | Cust "Pack" | DoPack | DontPack | @'DontPack'@ | | not dot |+| PackMode | packmode | G | Cust "PackMode" | | PackNode | @'PackNode'@ | | not dot |+| Pad | pad | G | Cust "DPoint" | | (DVal 0.0555) | @'DVal' 0.0555@ (4 points) | | |+| Page | page | G | Cust "Point" | | | | | |+| PageDir | pagedir | G | Cust "PageDir" | | Bl | @'Bl'@ | | |+| PenColor | pencolor | C | Cust "Color" | | (X11Color Black) | @'X11Color' 'Black'@ | | |+| PenWidth | penwidth | CNE | Dbl | | 1 | @1.0@ | @0.0@ | |+| Peripheries | peripheries | NC | Integ | | 1 | shape default (nodes), @1@ (clusters) | 0 | |+| Pin | pin | N | Bl | True | False | @'False'@ | | fdp, neato only |+| Pos | pos | EN | Cust "Pos" | | | | | |+| QuadTree | quadtree | G | Cust "QuadType" | NormalQT | NormalQT | @'NormalQT'@ | | sfdp only |+| Quantum | quantum | G | Dbl | | 0 | @0.0@ | @0.0@ | |+| Rank | rank | S | Cust "RankType" | | | | | dot only |+| RankDir | rankdir | G | Cust "RankDir" | | FromTop | @'FromTop'@ | | dot only |+| RankSep | ranksep | G | Cust "[Double]" | | | @[0.5]@ (dot), @[1.0]@ (twopi) | [0.02] | twopi, dot only |+| Ratio | ratio | G | Cust "Ratios" | | | | | |+| Rects | rects | N | Cust "[Rect]" | | | | | write only |+| Regular | regular | N | Bl | True | False | @'False'@ | | |+| ReMinCross | remincross | G | Bl | True | False | @'False'@ | | dot only |+| RepulsiveForce | repulsiveforce | G | Dbl | | 1 | @1.0@ | @0.0@ | sfdp only |+| Root | root | GN | Cust "Root" | IsCentral | (NodeName \"\") | @'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes) | | circo, twopi only |+| Rotate | rotate | G | Integ | | 0 | @0@ | | |+| Rotation | rotation | G | Dbl | | 0 | @0@ | | sfdp only, requires Graphviz >= 2.28.0 |+| SameHead | samehead | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |+| SameTail | sametail | E | Strng | | \"\" | @\\\"\\\"@ | | dot only |+| SamplePoints | samplepoints | N | Integ | | | @8@ (output), @20@ (overlap and image maps) | | |+| Scale | scale | G | Cust "DPoint" | | | | | twopi only, requires Graphviz >= 2.28.0 |+| SearchSize | searchsize | G | Integ | | 30 | @30@ | | dot only |+| Sep | sep | G | Cust "DPoint" | | (DVal 4) | @'DVal' 4@ | | not dot |+| Shape | shape | N | Cust "Shape" | | Ellipse | @'Ellipse'@ | | |+| ShapeFile | shapefile | N | Strng | | \"\" | @\\\"\\\"@ | | |+| ShowBoxes | showboxes | ENG | Integ | | 0 | @0@ | @0@ | dot only |+| Sides | sides | N | Integ | | 4 | @4@ | @0@ | |+| Size | size | G | Cust "GraphSize" | | | | | |+| Skew | skew | N | Dbl | | 0 | @0.0@ | @-100.0@ | |+| Smoothing | smoothing | G | Cust "SmoothType" | | NoSmooth | @'NoSmooth'@ | | sfdp only |+| SortV | sortv | GCN | Cust "Word16" | | 0 | @0@ | @0@ | |+| Splines | splines | G | Cust "EdgeType" | SplineEdges | SplineEdges | | | |+| Start | start | G | Cust "StartType" | | | | | fdp, neato only |+| Style | style | ENC | Cust "[StyleItem]" | | | | | |+| StyleSheet | stylesheet | G | Strng | | \"\" | @\\\"\\\"@ | | svg only |+| TailURL | tailURL tailhref | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, map only |+| TailClip | tailclip | E | Bl | True | True | @'True'@ | | |+| TailLabel | taillabel | E | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | |+| TailPort | tailport | E | Cust "PortPos" | | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@ | | |+| TailTarget | tailtarget | E | EStrng | | \"\" | none | | svg, map only |+| TailTooltip | tailtooltip | E | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| Target | target | ENGC | EStrng | | \"\" | none | | svg, map only |+| Tooltip | tooltip | NEC | EStrng | | \"\" | @\\\"\\\"@ | | svg, cmap only |+| TrueColor | truecolor | G | Bl | True | | | | bitmap output only |+| Vertices | vertices | N | Cust "[Point]" | | | | | write only |+| ViewPort | viewport | G | Cust "ViewPort" | | | none | | |+| VoroMargin | voro_margin | G | Dbl | | 0.05 | @0.05@ | @0.0@ | not dot |+| Weight | weight | E | Dbl | | | @1.0@ | @0@ (dot), @1@ (neato,fdp,sfdp) | |+| Width | width | N | Dbl | | 0.75 | @0.75@ | @0.01@ | |+| XLabel | xlabel | EN | Cust "Label" | | (StrLabel \"\") | @'StrLabel' \\\"\\\"@ | | requires Graphviz >= 2.29.0 |+| Z | z | N | Dbl | | 0 | @0.0@ | @-MAXFLOAT@, @-1000@ | |++-}+ unknownAttr :: Doc unknownAttr = text "UnknownAttribute" +-- For testing purposes+attrs :: [Attribute] attrs = take 10 $ drop 5 attributes +-- For testing purposes+attrs' :: Atts attrs' = AS (text "Attribute") attrs bool :: a -> a -> Bool -> a@@ -617,3 +823,12 @@ dollar :: Doc dollar = char '$'+++-- Local Variables:+-- eval: (turn-on-orgtbl)+-- eval: (defun cell-quote (s) (concat "\"" s "\""))+-- eval: (defun cell-parens (s) (concat "(" s ")"))+-- eval: (defun cell-to-maybe (s) (if (string= "" s) "Nothing" (cell-parens (concat "Just " (cell-quote s)))))+-- eval: (defun cell-to-list (s) (concat "[" (mapconcat 'cell-quote (split-string s) ", ") "]"))+-- END: