From 07d902912ca853e0ccafd4272b20f5ba15391ee5 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 21 Jun 2024 10:41:25 +0100 Subject: [PATCH 1/5] doc: fix compile --- gap/dot.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/dot.gd b/gap/dot.gd index b91b7f8..21737a4 100644 --- a/gap/dot.gd +++ b/gap/dot.gd @@ -116,7 +116,7 @@ DeclareOperation("GraphvizContexts", [IsGraphvizGraphDigraphOrContext]); #! Searches through the tree of subgraphs connected to this subgraph for a graph #! with the provided name. #! It returns the graph if it exists. -#! If no such graph exists then it will return fail. +#! If no such graph exists then it will return fail. DeclareOperation("GraphvizFindSubgraphRecursive", [IsGraphvizGraphDigraphOrContext, IsObject]); From eb2f423e9f1922b608e910bf3fed7d911a201f89 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 21 Jun 2024 12:13:26 +0100 Subject: [PATCH 2/5] doc: add more preamble --- PackageInfo.g | 30 +++++++- gap/dot.gd | 188 ++++++++++++++++++++++++++++++++++++++++++++++---- gap/splash.gd | 84 ++++++++++++++++++++++ gap/splash.gi | 4 +- makedoc.g | 29 +++++++- 5 files changed, 314 insertions(+), 21 deletions(-) diff --git a/PackageInfo.g b/PackageInfo.g index cfb5046..c61f6d1 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -55,8 +55,6 @@ ArchiveURL := Concatenation(~.PackageWWWHome, ~.Version), ArchiveFormats := ".tar.gz", -AbstractHTML := "TODO", - PackageDoc := rec( BookName := "graphviz", ArchiveURLSubset := ["doc"], @@ -75,4 +73,30 @@ Dependencies := rec( AvailabilityTest := ReturnTrue, -TestFile := "tst/testall.g")); +TestFile := "tst/testall.g", + +AutoDoc := rec( + TitlePage := rec( + Copyright := """©right; by J. D. Mitchell and M. Pancer.

+ &GAPGraphviz; is free software; you can redistribute it and/or modify + it, under the terms of the GNU General Public License, version 3 of + the License, or (at your option) any later, version.""", + Abstract := """ + This package facilitates the creation and rendering of graph + descriptions in the ˙ language of the &Graphviz; graph drawing + software from ⪆. +

+ + Create a graphviz object, assemble the graph by adding nodes and edges, + and retrieve its ˙ source code string. Save the source code to a file + and render it with the &Graphviz; installation of your system. +

+ + Use the function to directly inspect the resulting + graph. +

+ + This package was inspired by the python package of the same name + &PyGraphviz;.""")), + +AbstractHTML := ~.AutoDoc.TitlePage.Abstract)); diff --git a/gap/dot.gd b/gap/dot.gd index 21737a4..a88f5fc 100644 --- a/gap/dot.gd +++ b/gap/dot.gd @@ -9,25 +9,174 @@ ## #! @Chapter -#! @ChapterTitle An introduction to the DOT language and Graphviz. -#! This chapter explains what the DOT and graphviz are, -#! key basic concepts relating to them, and how this package interacts with them. - -#! @Section A Brief Introduction -#! DOT is a language for descrbing to a computer how to display a visualization -#! for a graph or digraph. Graphviz is a graph visualization software which can -#! consume DOT and produce visual outputs. This package is designed to allow -#! users to programmatically construct objects in GAP which can then be -#! converted into DOT. That DOT can then be inputted into the graphviz software -#! to produce a visual output. As DOT is central to the design of this package +#! @ChapterTitle Getting started +#! This chapter very briefly explains what ˙ and &Graphviz; are, provides +#! some key basic concepts relating to them, and how this package interacts +#! with them. + +#! @Section A brief introduction +#! ˙ is a language for descrbing to a computer how to display a visualization +#! of a graph or digraph. &Graphviz; is a graph visualization software which can +#! consume ˙ and produce visual outputs. This package is designed to allow +#! users to programmatically construct objects in ⪆ which can then be +#! converted into ˙. That ˙ can then be input to the &Graphviz; software +#! to produce a visual output. As ˙ is central to the design of this package #! it will likely be helpful to have a basic understanding of the language. -#! For more information about DOT see +#! For more information about ˙ see #! https://graphviz.org/doc/info/lang.html. - -#! @Chapter -#! @ChapterTitle The Graphviz Package +#!

+#! +#! The &GAPGraphviz; package for ⪆ is intended to facilitate the creation +#! and rendering of graph descriptions in the ˙ language of the &Graphviz; +#! graph drawing software. +#!

+#! +#! You can create a &GAPGraphviz; object, assemble the graph by adding nodes +#! and edges, setting attributes, labels and so on, and retrieve its ˙ +#! source code string. You can save the source code +#! to a file (using ) and render it +#! with the &Graphviz; installation of your system; or you can +#! use the function to directly inspect the resulting +#! graph (depending on your system and the software installed). + +#! @Section What this package is not +#! +#! This package does not implement a parser of the ˙ language and does only +#! minimal checks when assembling a graph. In particular, if you set attributes +#! which don't exist in ˙, then the resulting string might not be valid, +#! and might not render correctly using &Graphviz;. + +#! @Section A first example +#! Here's an example of how to use the &GAPGraphviz; package, to construct a +#! ˙ representation of a finite state automata. This example is taken from +#! https://graphviz.readthedocs.io/en/stable/examples.html or +#! https://graphviz.org/Gallery/directed/fsm.html. +#! +#! @BeginExampleSession +#! gap> LoadPackage("graphviz");; +#! gap> f := GraphvizDigraph("finite_state_machine"); +#! +#! gap> GraphvizSetAttr(f, "rankdir=LR"); +#! +#! gap> GraphvizSetAttr(f, "size=\"8,5\""); +#! +#! gap> terminals := GraphvizAddContext(f, "terminals"); +#! +#! gap> GraphvizSetAttr(terminals, "node [shape=doublecircle]"); +#! +#! gap> GraphvizAddNode(terminals, "LR_0"); +#! +#! gap> GraphvizAddNode(terminals, "LR_3"); +#! +#! gap> GraphvizAddNode(terminals, "LR_4"); +#! +#! gap> GraphvizAddNode(terminals, "LR_8"); +#! +#! gap> nodes := GraphvizAddContext(f, "nodes"); +#! +#! gap> GraphvizSetAttr(nodes, "node [shape=circle]"); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_0", "LR_2"), +#! > "label", "\"SS(B)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_0", "LR_1"), +#! > "label", "\"SS(S)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_1", "LR_3"), +#! "label", "\"S($end)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_2", "LR_6"), +#! > "label", "\"SS(b)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_2", "LR_5"), +#! > "label", "\"SS(a)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_2", "LR_4"), +#! > "label", "\"S(A)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_5", "LR_7"), +#! > "label", "\"S(b)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_5", "LR_5"), +#! > "label", "\"S(a)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_6", "LR_6"), +#! > "label", "\"S(b)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_6", "LR_5"), +#! > "label", "\"S(a)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_7", "LR_8"), +#! > "label", "\"S(b)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_7", "LR_5"), +#! > "label", "\"S(a)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_8", "LR_6"), +#! > "label", "\"S(b)\""); +#! +#! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_8", "LR_5"), +#! > "label", "\"S(a)\""); +#! +#! gap> Print(AsString(f), "\n"); +#! //dot +#! digraph finite_state_machine { +#! rankdir=LR size="8,5" +#! // terminals context +#! node [shape=doublecircle] +#! LR_0 +#! LR_3 +#! LR_4 +#! LR_8 +#! rankdir=LR size="8,5" +#! +#! // nodes context +#! node [shape=circle] +#! LR_2 +#! LR_0 -> LR_2 [label="SS(B)"] +#! LR_1 +#! LR_0 -> LR_1 [label="SS(S)"] +#! LR_1 -> LR_3 [label="S($end)"] +#! LR_6 +#! LR_2 -> LR_6 [label="SS(b)"] +#! LR_5 +#! LR_2 -> LR_5 [label="SS(a)"] +#! LR_2 -> LR_4 [label="S(A)"] +#! LR_7 +#! LR_5 -> LR_7 [label="S(b)"] +#! LR_5 -> LR_5 [label="S(a)"] +#! LR_6 -> LR_6 [label="S(b)"] +#! LR_6 -> LR_5 [label="S(a)"] +#! LR_7 -> LR_8 [label="S(b)"] +#! LR_7 -> LR_5 [label="S(a)"] +#! LR_8 -> LR_6 [label="S(b)"] +#! LR_8 -> LR_5 [label="S(a)"] +#! rankdir=LR size="8,5" +#! +#! } +#! gap> Splash(f); +#! @EndExampleSession +#! +#! Provided that you have &Graphviz; installed on your computer, the last line +#! of the example Splash(f) will produce the following picture: +#! +#! +#! +#! +#! +#! ]]> +#! +#! +#! There are lots more examples in the examples directory within the +#! &Graphviz; package for ⪆ directory. + +#! @Chapter Full Reference +#! This chapter contains all of the gory details about the functionality of the +#! &GAPGraphviz; package for ⪆. #! @Section Graphviz Categories +#! Blurg #! @BeginGroup Filters #! @Description Every object in graphviz belongs to the IsGraphvizObject @@ -36,16 +185,25 @@ #! All are direct subcategories of IsGraphvizObject excluding IsGraphvizDigraph #! which is a subcategory of is IsGraphvizGraph. +#! TODO DeclareCategory("IsGraphvizObject", IsObject); +#! TODO DeclareCategory("IsGraphvizGraphDigraphOrContext", IsGraphvizObject); +#! TODO DeclareCategory("IsGraphvizGraph", IsGraphvizGraphDigraphOrContext); +#! TODO DeclareCategory("IsGraphvizDigraph", IsGraphvizGraphDigraphOrContext); +#! TODO DeclareCategory("IsGraphvizContext", IsGraphvizGraphDigraphOrContext); +#! TODO DeclareCategory("IsGraphvizNodeOrEdge", IsGraphvizObject); +#! TODO DeclareCategory("IsGraphvizNode", IsGraphvizNodeOrEdge); +#! TODO DeclareCategory("IsGraphvizEdge", IsGraphvizNodeOrEdge); + #! @EndGroup #! @Section Constructors diff --git a/gap/splash.gd b/gap/splash.gd index 919a68a..22e9857 100644 --- a/gap/splash.gd +++ b/gap/splash.gd @@ -12,4 +12,88 @@ # function was written by A. Egri-Nagy and Manuel Delgado, with some minor # modifications by J. Mitchell. +#! @ChapterInfo Full Reference, Outputting +#! @Arguments x[, opts] +#! @Returns Nothing. +#! @Description +#! This function attempts to convert the string str into a pdf +#! document and open this document, i.e. to splash it all over your monitor.

+#! +#! The argument x must be one of: TODO +#! +#! must correspond to a valid dot or +#! LaTeX text file and you must have have GraphViz and +#! pdflatex installed on your computer. For details about these file +#! formats, see https://www.latex-project.org and +#! https://www.graphviz.org.

+#! +#! The optional second argument opts should be a record with +#! components corresponding to various options, given below. +#! +#! +#! path +#! +#! this should be a string representing the path to the directory where +#! you want Splash to do its work. The default value of this +#! option is "~/". +#! +#! +#! directory +#! +#! this should be a string representing the name of the directory in +#! path where you want Splash to do its work. This function +#! will create this directory if does not already exist.

+#! +#! The default value of this option is "tmp.viz" if the option +#! path is present, and the result of +#! is used otherwise. +#! +#! +#! filename +#! +#! this should be a string representing the name of the file where +#! str will be written. The default value of this option is +#! "vizpicture". +#! +#! +#! viewer +#! +#! this should be a string representing the name of the program which +#! should open the files produced by GraphViz or pdflatex. +#! +#! +#! type +#! +#! this option can be used to specify that the string str contains +#! a &LaTeX; or dot document. You can specify this option in +#! str directly by making the first line "%latex" or +#! "//dot". There is no default value for this option, this +#! option must be specified in str or in opt.type. +#! +#! +#! engine +#! +#! this option can be used to specify the GraphViz engine to use +#! to render a dot document. The valid choices are "dot", +#! "neato", "circo", "twopi", "fdp", +#! "sfdp", and "patchwork". Please refer to the +#! GraphViz documentation for details on these engines. +#! The default value for this option is "dot", and it +#! must be specified in opt.engine. +#! +#! +#! filetype +#! +#! this should be a string representing the type of file which +#! Splash should produce. For &LaTeX; files, this option is +#! ignored and the default value "pdf" is used. +#! +#! +#! +#! This function was originally written by Attila Egri-Nagy and Manuel Delgado, +#! the present version incorporates some minor changes.

+#! @BeginLogSession +#! gap> TODO +#! gap> Splash(); +#! @EndLogSession DeclareGlobalFunction("Splash"); diff --git a/gap/splash.gi b/gap/splash.gi index 9d3c67e..41a3da2 100644 --- a/gap/splash.gi +++ b/gap/splash.gi @@ -32,7 +32,7 @@ function(arg...) file[i] := '_'; fi; od; - arg[1] := String(arg[1]); + arg[1] := AsString(arg[1]); else file := "vizpicture"; fi; @@ -42,7 +42,7 @@ function(arg...) if IsBound(arg[2]) and IsRecord(arg[2]) then opt := arg[2]; elif IsBound(arg[2]) then - ErrorNoReturn("the 2nd argument must be a record,"); + ErrorNoReturn("the 2nd argument must be a record"); fi; path := UserHomeExpand("~/"); diff --git a/makedoc.g b/makedoc.g index a04d383..5e2725f 100644 --- a/makedoc.g +++ b/makedoc.g @@ -10,9 +10,36 @@ ## This file is a script which compiles the package manual. +UrlEntity := function(name, url) + return StringFormatted("""{2} + {1}""", name, url); +end; + +PackageEntity := function(name) + if TestPackageAvailability(name) <> fail then + return UrlEntity(PackageInfo(name)[1].PackageName, + PackageInfo(name)[1].PackageWWWHome); + fi; + return StringFormatted("{1}", name); +end; + if fail = LoadPackage("AutoDoc", "2022.10.20") then Error("AutoDoc version 2022.10.20 or newer is required."); fi; -AutoDoc(rec(scaffold := true, autodoc := true)); +XMLEntities := rec(); + +XMLEntities.GAPGraphviz := PackageEntity("Graphviz"); +XMLEntities.PyGraphviz := UrlEntity("graphviz", + "https://pypi.org/project/graphviz/"); +XMLEntities.DOT := UrlEntity("DOT", + "https://www.graphviz.org/doc/info/lang.html"); +XMLEntities.Graphviz := UrlEntity("Graphviz", "https://www.graphviz.org"); + +AutoDoc("graphviz", +rec(scaffold := rec(entities := XMLEntities), autodoc := true)); + +Unbind(PackageEntity); +Unbind(UrlEntity); +Unbind(XMLEntities); QUIT; From a227e6c166445050dabe5b6a51a7c4c618b4925e Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 21 Jun 2024 12:58:21 +0100 Subject: [PATCH 3/5] README: incomplete 1st draft --- README.md | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7242a81..0ca4068 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,191 @@ -# The GAP package graphviz +## README -TODO: add a description of your package; perhaps also instructions how how to -install and use it, resp. where to find out more +### Graphviz package for GAP -## Contact +#### Copyright (C) 2024 by J. D. Mitchell and M. Pancer -TODO: add info on how to contact you and/or how to report issues with your -package +## Graphviz for GAP + +This package facilitates the creation and rendering of graph +descriptions in the [DOT][] language of the [Graphviz][] graph drawing +software from [GAP][]. + +You can create a graphviz object, assemble the graph by adding nodes and +edges, attributes, labels, colours, subgraphs, and clusters, and +retrieve its [DOT][] source code string. Save the source code to a file +and render it with the [Graphviz] installation on your system. + +You can use the [Splash] function to directly inspect the resulting +graph. + +This package was inspired by the python package of the same name +[Python Graphviz]. + +## Links + +- GitHub: https://github.com/xflr6/graphviz +- Documentation: https://graphviz.readthedocs.io +- Changelog: https://graphviz.readthedocs.io/en/latest/changelog.html +- Issue Tracker: https://github.com/xflr6/graphviz/issues +- Download: https://pypi.org/project/graphviz/#files + +## Installation + +This package requires [GAP][] version 4.11.0 or higher. The most +up-to-date version of GAP, and instructions on how to install it, can be +obtained from the [main GAP webpage](https://www.gap-system.org). This +package has no further dependencies! + +### From sources + +To get the latest version of the package, download the archive file +`graphviz-x.x.x.tar.gz` from the [Graphviz webpage][]. Then, inside the +`pkg` subdirectory of your GAP installation, unpack the archive +`graphviz-x.x.x.tar.gz` in your `gap/pkg` directory, using + + gunzip graphviz-x.x.x.tar.gz; tar xvf graphviz-x.x.x.tar + +for example. This will create a subdirectory `graphviz-x.x.x`. + +### Using the [PackageManager][] + +Start GAP in the usual way, then type: + + LoadPackage("PackageManager"); + InstallPackage("graphviz"); + +## Quickstart + +Create a graph object: + + gap> LoadPackage("graphviz"); + ─────────────────────────────────────────────────────────────────────────────────── + Loading graphviz 0.0.0 (TODO) + by James D. Mitchell (https://jdbm.me) and + Matthew Pancer (mp322@st-andrews.ac.uk). + Homepage: https://digraphs.github.io/graphviz + Report issues at https://github.com/digraphs/graphviz/issues + ─────────────────────────────────────────────────────────────────────────────────── + true + gap> dot := GraphvizDigraph("The Round Table"); + + +Add nodes and edges: + + gap> GraphvizSetAttr(GraphvizAddNode(dot, "A"), "label", "King Arthur"); + + gap> GraphvizSetAttr(GraphvizAddNode(dot, "B"), "label", "Sir Bedevere the Wise"); + + gap> GraphvizSetAttr(GraphvizAddNode(dot, "L"), "label", "Sir Lancelot the Brave"); + + gap> GraphvizAddEdge(dot, "A", "B"); + + gap> GraphvizAddEdge(dot, "A", "L"); + + gap> GraphvizSetAttr(GraphvizAddEdge(dot, "B", "L"), "constraint", false); + +Check the generated source code: + + gap> Print(AsString(dot)); + //dot + digraph { + A [label="King Arthur"] + B [label="Sir Bedevere the Wise"] + L [label="Sir Lancelot the Brave"] + A -> B + A -> L + B -> L [constraint=false] + } + +Save the source code: + + gap> FileString(TODO + +Save and render and view the result: + +.. code:: python + + >>> doctest_mark_exe() # skip this line + + >>> dot.render('doctest-output/round-table.gv', view=True) # doctest: +SKIP + 'doctest-output/round-table.gv.pdf' + +.. image:: https://raw.github.com/xflr6/graphviz/master/docs/_static/round-table.svg + :align: center + :alt: round-table.svg + +**Caveat:** +Backslash-escapes and strings of the form ``<...>`` +have a special meaning in the DOT language. +If you need to render arbitrary strings (e.g. from user input), +check the details in the `user guide`_. + +## Issues + +For questions, remarks, suggestions, and issues please use the +[issue tracker](https://github.com/digraphs/graphviz/issues). ## License -TODO: Provide information on the license of your package. A license is -important as it determines who has a right to distribute your package. The -"default" license to consider is GNU General Public License v2 or later, as -that is the license of GAP itself. +This package is distributed under the GNU General Public License v2 or later. +See the `LICENSE` file for more details. + +[PackageManager]: https://gap-packages.github.io/PackageManager +[Graphviz webpage]: https://digraphs.github.io/Digraphs +[GAP]: https://www.gap-system.org + + + +See also +-------- + +- pygraphviz_ |--| full-blown interface wrapping the Graphviz C library with SWIG +- graphviz-python_ |--| official Python bindings + (`documentation `_) +- pydot_ |--| stable pure-Python approach, requires pyparsing + + +License +------- + +This package is distributed under the `MIT license`_. + + +.. _Graphviz: https://www.graphviz.org +.. _DOT: https://www.graphviz.org/doc/info/lang.html +.. _upstream repo: https://gitlab.com/graphviz/graphviz/ +.. _upstream-download: https://www.graphviz.org/download/ +.. _upstream-archived: https://www2.graphviz.org/Archive/stable/ +.. _upstream-windows: https://forum.graphviz.org/t/new-simplified-installation-procedure-on-windows/224 + +.. _set-path-windows: https://www.computerhope.com/issues/ch000549.htm +.. _set-path-linux: https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix +.. _set-path-darwin: https://stackoverflow.com/questions/22465332/setting-path-environment-variable-in-osx-permanently + +.. _pip: https://pip.pypa.io + +.. _Jupyter notebooks: https://jupyter.org +.. _IPython notebooks: https://ipython.org/notebook.html +.. _Jupyter QtConsole: https://qtconsole.readthedocs.io + +.. _notebook: https://github.com/xflr6/graphviz/blob/master/examples/graphviz-notebook.ipynb +.. _notebook-nbviewer: https://nbviewer.org/github/xflr6/graphviz/blob/master/examples/graphviz-notebook.ipynb + +.. _Anaconda: https://docs.anaconda.com/anaconda/install/ +.. _conda-forge: https://conda-forge.org +.. _conda-forge-python-graphviz: https://anaconda.org/conda-forge/python-graphviz +.. _conda-forge-python-graphviz-feedstock: https://github.com/conda-forge/python-graphviz-feedstock +.. _conda-forge-graphviz: https://anaconda.org/conda-forge/graphviz +.. _conda-forge-graphviz-feedstock: https://github.com/conda-forge/graphviz-feedstock + +.. _user guide: https://graphviz.readthedocs.io/en/stable/manual.html + +.. _pygraphviz: https://pypi.org/project/pygraphviz/ +.. _graphviz-python: https://pypi.org/project/graphviz-python/ +.. _graphviz-python-docs: https://www.graphviz.org/pdf/gv.3python.pdf +.. _pydot: https://pypi.org/project/pydot/ + +.. _MIT license: https://opensource.org/licenses/MIT + + +.. |--| unicode:: U+2013 From f519072e63ae1f73e5d995c882d5da8a38b34d6a Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 21 Jun 2024 15:26:06 +0100 Subject: [PATCH 4/5] README: more complete 2nd draft --- README.md | 117 ++++++++++++------------------------------------------ 1 file changed, 26 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 0ca4068..8b0cb2c 100644 --- a/README.md +++ b/README.md @@ -19,15 +19,20 @@ You can use the [Splash] function to directly inspect the resulting graph. This package was inspired by the python package of the same name -[Python Graphviz]. +[Python Graphviz][]. + +## License + +This package is distributed under the GNU General Public License v2 or later. +See the `LICENSE` file for more details. ## Links -- GitHub: https://github.com/xflr6/graphviz -- Documentation: https://graphviz.readthedocs.io -- Changelog: https://graphviz.readthedocs.io/en/latest/changelog.html -- Issue Tracker: https://github.com/xflr6/graphviz/issues -- Download: https://pypi.org/project/graphviz/#files +- GitHub: [https://github.com/digraphs/graphviz](https://github.com/digraphs/graphviz) +- Documentation: TODO +- Changelog: TODO +- Issue Tracker: [https://github.com/digraphs/graphviz/issues](https://github.com/digraphs/graphviz/issues) +- Download: TODO ## Installation @@ -39,9 +44,9 @@ package has no further dependencies! ### From sources To get the latest version of the package, download the archive file -`graphviz-x.x.x.tar.gz` from the [Graphviz webpage][]. Then, inside the -`pkg` subdirectory of your GAP installation, unpack the archive -`graphviz-x.x.x.tar.gz` in your `gap/pkg` directory, using +`graphviz-x.x.x.tar.gz` from the [Graphviz package for GAP webpage][]. +Then, inside the `pkg` subdirectory of your GAP installation, unpack the +archive `graphviz-x.x.x.tar.gz` in your `gap/pkg` directory, using gunzip graphviz-x.x.x.tar.gz; tar xvf graphviz-x.x.x.tar @@ -51,8 +56,8 @@ for example. This will create a subdirectory `graphviz-x.x.x`. Start GAP in the usual way, then type: - LoadPackage("PackageManager"); - InstallPackage("graphviz"); + LoadPackage("PackageManager"); + InstallPackage("graphviz"); ## Quickstart @@ -99,93 +104,23 @@ Check the generated source code: Save the source code: - gap> FileString(TODO + gap> FileString("round-table.gv", AsString(dot)); + 134 -Save and render and view the result: +Render and view the result: -.. code:: python + gap> Splash(dot); - >>> doctest_mark_exe() # skip this line - - >>> dot.render('doctest-output/round-table.gv', view=True) # doctest: +SKIP - 'doctest-output/round-table.gv.pdf' - -.. image:: https://raw.github.com/xflr6/graphviz/master/docs/_static/round-table.svg - :align: center - :alt: round-table.svg - -**Caveat:** -Backslash-escapes and strings of the form ``<...>`` -have a special meaning in the DOT language. -If you need to render arbitrary strings (e.g. from user input), -check the details in the `user guide`_. +![The Round Table](https://raw.github.com/digraphs/graphviz/main/docs/png/The_Round_Table.png) ## Issues For questions, remarks, suggestions, and issues please use the [issue tracker](https://github.com/digraphs/graphviz/issues). -## License - -This package is distributed under the GNU General Public License v2 or later. -See the `LICENSE` file for more details. - -[PackageManager]: https://gap-packages.github.io/PackageManager -[Graphviz webpage]: https://digraphs.github.io/Digraphs +[DOT]: https://www.graphviz.org/doc/info/lang.html [GAP]: https://www.gap-system.org - - - -See also --------- - -- pygraphviz_ |--| full-blown interface wrapping the Graphviz C library with SWIG -- graphviz-python_ |--| official Python bindings - (`documentation `_) -- pydot_ |--| stable pure-Python approach, requires pyparsing - - -License -------- - -This package is distributed under the `MIT license`_. - - -.. _Graphviz: https://www.graphviz.org -.. _DOT: https://www.graphviz.org/doc/info/lang.html -.. _upstream repo: https://gitlab.com/graphviz/graphviz/ -.. _upstream-download: https://www.graphviz.org/download/ -.. _upstream-archived: https://www2.graphviz.org/Archive/stable/ -.. _upstream-windows: https://forum.graphviz.org/t/new-simplified-installation-procedure-on-windows/224 - -.. _set-path-windows: https://www.computerhope.com/issues/ch000549.htm -.. _set-path-linux: https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix -.. _set-path-darwin: https://stackoverflow.com/questions/22465332/setting-path-environment-variable-in-osx-permanently - -.. _pip: https://pip.pypa.io - -.. _Jupyter notebooks: https://jupyter.org -.. _IPython notebooks: https://ipython.org/notebook.html -.. _Jupyter QtConsole: https://qtconsole.readthedocs.io - -.. _notebook: https://github.com/xflr6/graphviz/blob/master/examples/graphviz-notebook.ipynb -.. _notebook-nbviewer: https://nbviewer.org/github/xflr6/graphviz/blob/master/examples/graphviz-notebook.ipynb - -.. _Anaconda: https://docs.anaconda.com/anaconda/install/ -.. _conda-forge: https://conda-forge.org -.. _conda-forge-python-graphviz: https://anaconda.org/conda-forge/python-graphviz -.. _conda-forge-python-graphviz-feedstock: https://github.com/conda-forge/python-graphviz-feedstock -.. _conda-forge-graphviz: https://anaconda.org/conda-forge/graphviz -.. _conda-forge-graphviz-feedstock: https://github.com/conda-forge/graphviz-feedstock - -.. _user guide: https://graphviz.readthedocs.io/en/stable/manual.html - -.. _pygraphviz: https://pypi.org/project/pygraphviz/ -.. _graphviz-python: https://pypi.org/project/graphviz-python/ -.. _graphviz-python-docs: https://www.graphviz.org/pdf/gv.3python.pdf -.. _pydot: https://pypi.org/project/pydot/ - -.. _MIT license: https://opensource.org/licenses/MIT - - -.. |--| unicode:: U+2013 +[Graphviz]: https://www.graphviz.org +[Graphviz webpage]: https://digraphs.github.io/Digraphs +[PackageManager]: https://gap-packages.github.io/PackageManager +[Python Graphviz]: https://pypi.org/project/graphviz/ From d29c5a99fb9a8b6bffd02193a1d8839d32329137 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 21 Jun 2024 17:09:23 +0100 Subject: [PATCH 5/5] More doc --- gap/dot.gd | 225 +++++++++++++++++++++++++++++++++++++++++--------- gap/dot.gi | 16 ++-- gap/gv.gi | 5 +- makedoc.g | 5 +- tst/testall.g | 2 +- 5 files changed, 201 insertions(+), 52 deletions(-) diff --git a/gap/dot.gd b/gap/dot.gd index a88f5fc..9ab342b 100644 --- a/gap/dot.gd +++ b/gap/dot.gd @@ -34,7 +34,7 @@ #! You can create a &GAPGraphviz; object, assemble the graph by adding nodes #! and edges, setting attributes, labels and so on, and retrieve its &DOT; #! source code string. You can save the source code -#! to a file (using ) and render it +#! to a file (using ) and render it #! with the &Graphviz; installation of your system; or you can #! use the function to directly inspect the resulting #! graph (depending on your system and the software installed). @@ -52,7 +52,7 @@ #! https://graphviz.readthedocs.io/en/stable/examples.html or #! https://graphviz.org/Gallery/directed/fsm.html. #! -#! @BeginExampleSession +#! @BeginLogSession #! gap> LoadPackage("graphviz");; #! gap> f := GraphvizDigraph("finite_state_machine"); #! @@ -83,7 +83,7 @@ #! > "label", "\"SS(S)\""); #! #! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_1", "LR_3"), -#! "label", "\"S($end)\""); +#! > "label", "\"S($end)\""); #! #! gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_2", "LR_6"), #! > "label", "\"SS(b)\""); @@ -155,10 +155,10 @@ #! #! } #! gap> Splash(f); -#! @EndExampleSession +#! @EndLogSession #! #! Provided that you have &Graphviz; installed on your computer, the last line -#! of the example Splash(f) will produce the following picture: +#! of the example Splash(f) would produce the following picture: #! #! #! IsGraphvizObject #! category. The categories following it are for further specificity on the -#! type of objects. These are graphs, digraphs, nodes and edges respectively. -#! All are direct subcategories of IsGraphvizObject excluding IsGraphvizDigraph -#! which is a subcategory of is IsGraphvizGraph. - -#! TODO +#! type of objects. These are graphs, digraphs, contexts, nodes, and +#! edges, and combinations of these that have some common features. DeclareCategory("IsGraphvizObject", IsObject); - -#! TODO DeclareCategory("IsGraphvizGraphDigraphOrContext", IsGraphvizObject); -#! TODO DeclareCategory("IsGraphvizGraph", IsGraphvizGraphDigraphOrContext); -#! TODO DeclareCategory("IsGraphvizDigraph", IsGraphvizGraphDigraphOrContext); -#! TODO DeclareCategory("IsGraphvizContext", IsGraphvizGraphDigraphOrContext); - -#! TODO DeclareCategory("IsGraphvizNodeOrEdge", IsGraphvizObject); -#! TODO DeclareCategory("IsGraphvizNode", IsGraphvizNodeOrEdge); -#! TODO DeclareCategory("IsGraphvizEdge", IsGraphvizNodeOrEdge); - +#! The names of these categories are fairly descriptive, where a graph +#! has undirected edges, a digraph has directed edges, and a context is +#! a part of a &Graphviz; file/string consisting of objects (nodes, +#! edges, further contexts, subgraphs etc) that share some common +#! attributes. #! @EndGroup #! @Section Constructors #! @BeginGroup -#! @GroupTitle Constructors for Graphs +#! @GroupTitle Creating a new &GAPGraphviz; graphs #! @Arguments name -#! @Returns a new graphviz graph -#! @Description Creates a new graphviz graph optionally with the provided name. +#! @Returns A new &GAPGraphviz; graph. +#! @Description These operations create a new &GAPGraphviz; graph objects. +#! +#! In the first form, the created &GAPGraphviz; graph object has name +#! name. In the second form, the constructed &GAPGraphviz; graph +#! object has an empty string as a name. +#! +#! The argument name can be any &GAP; object for which there is a +#! method, and the name of the +#! created object will be equal to String(name). +#! +#! A "graph" in &Graphviz; has undirected edges that are represented +#! using the string "--" in the &DOT; language. +#! +#! See also: +#! * +#! * +#! * +#! +#! @BeginExampleSession +#! gap> gv := GraphvizGraph("GraphyMcGraphFace"); +#! +#! gap> GraphvizName(gv); +#! "GraphyMcGraphFace" +#! gap> GraphvizGraph(666); +#! +#! gap> gv := GraphvizGraph(); +#! +#! gap> GraphvizName(gv); +#! "" +#! @EndExampleSession DeclareOperation("GraphvizGraph", [IsObject]); DeclareOperation("GraphvizGraph", []); #! @EndGroup #! @BeginGroup -#! @GroupTitle Constructors for Digraphs +#! @GroupTitle Creating a new &GAPGraphviz; digraphs #! @Arguments name -#! @Returns a new graphviz digraph -#! @Description Creates a new graphviz digraph optionally with the provided name. +#! @Returns A new &GAPGraphviz; digraph. +#! @Description These operations create a new &GAPGraphviz; digraph objects. +#! +#! In the first form, the created &GAPGraphviz; digraph object has name +#! name. In the second form, the constructed &GAPGraphviz; digraph +#! object has an empty string as a name. +#! +#! The argument name can be any &GAP; object for which there is a +#! method, and the name of the +#! created object will be equal to String(name). +#! +#! A "digraph" in &Graphviz; has directed edges that are represented +#! using the string "->" in the &DOT; language. +#! +#! See also: +#! * +#! * +#! * +#! +#! @BeginExampleSession +#! gap> gv := GraphvizDigraph("GraphyMcGraphFace"); +#! +#! gap> GraphvizName(gv); +#! "GraphyMcGraphFace" +#! gap> GraphvizDigraph(666); +#! +#! gap> gv := GraphvizDigraph(); +#! +#! gap> GraphvizName(gv); +#! "" +#! @EndExampleSession DeclareOperation("GraphvizDigraph", [IsObject]); DeclareOperation("GraphvizDigraph", []); #! @EndGroup -#! @Section Get Operations -#! This section covers the operations for getting information about graphviz -#! objects. - -#! @Subsection For all graphviz objects. +#! @Section Getters for any object +#! This section covers the operations for getting information about +#! &GAPGraphviz; any object. #! @Arguments obj -#! @Returns the name of the provided graphviz object -#! @Description Gets the name of the provided graphviz object. +#! @Returns A string. +#! @Description If the argument obj is a &GAPGraphviz; object +#! (), then this +#! function returns the name of the &Graphviz; object obj. +#! +#! @BeginExampleSession +#! gap> dot := GraphvizDigraph("The Round Table");; +#! gap> GraphvizName(dot); +#! "The Round Table" +#! gap> n := GraphvizSetAttr(GraphvizAddNode(dot, "A"), "label", "King Arthur"); +#! gap> GraphvizName(n); +#! "A" +#! gap> e := GraphvizAddEdge(dot, "A", "B");; +#! gap> GraphvizName(e); +#! "(A, B)" +#! @EndExampleSession DeclareOperation("GraphvizName", [IsGraphvizObject]); #! @Arguments obj #! @Returns the attributes of the provided graphviz object #! @Description Gets the attributes of the provided graphviz object. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession +# HERE DeclareOperation("GraphvizAttrs", [IsGraphvizObject]); -#! @Subsection For only graphs and digraphs. +#! @Section Getters for graphs and digraphs #! @Arguments graph #! @Returns the nodes of the provided graphviz graph. @@ -255,17 +321,26 @@ DeclareOperation("GraphvizAttrs", [IsGraphvizObject]); # any double-quoted string ("...") possibly containing escaped quotes (\")¹; # an HTML string (<...>). # TODO specify +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizNodes", [IsGraphvizGraphDigraphOrContext]); #! @Arguments graph #! @Returns the subgraphs of the provided graphviz graph. #! @Description gets the subgraphs of a provided graphviz graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizSubgraphs", [IsGraphvizGraphDigraphOrContext]); #! @Arguments graph #! @Returns the contexts of the provided graphviz graph, digraph or context. #! @Description gets the contexts of a provided graphviz graph, digraph #! or context. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizContexts", [IsGraphvizGraphDigraphOrContext]); #! @Arguments graph, name @@ -275,12 +350,18 @@ DeclareOperation("GraphvizContexts", [IsGraphvizGraphDigraphOrContext]); #! with the provided name. #! It returns the graph if it exists. #! If no such graph exists then it will return fail. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizFindSubgraphRecursive", [IsGraphvizGraphDigraphOrContext, IsObject]); #! @Arguments graph #! @Returns the edges of the provided graphviz graph. #! @Description Gets the edges of the provided graphviz graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizEdges", [IsGraphvizGraphDigraphOrContext]); DeclareOperation("GraphvizEdges", [IsGraphvizGraphDigraphOrContext, IsObject, IsObject]); @@ -290,11 +371,17 @@ DeclareOperation("GraphvizEdges", #! @Arguments edge #! @Returns the head of the provided graphviz edge. #! @Description Gets the head of the provided graphviz graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizHead", [IsGraphvizEdge]); #! @Arguments edge #! @Returns the head of the provided graphviz tail. #! @Description Gets the tail of the provided graphviz graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizTail", [IsGraphvizEdge]); #! @Section Set Operations @@ -305,12 +392,18 @@ DeclareOperation("GraphvizTail", [IsGraphvizEdge]); #! @Arguments graph, name #! @Returns the modified graph. #! @Description Sets the name of a graphviz graph or digraph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizSetName", [IsGraphvizGraphDigraphOrContext, IsObject]); #! @Arguments graph, node #! @Returns the modified graph. #! @Description Adds a node to the graph. #! If a node with the same name is already present the operation fails. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizAddNode", [IsGraphvizGraphDigraphOrContext, IsObject]); #! @Arguments graph, edge @@ -321,12 +414,18 @@ DeclareOperation("GraphvizAddNode", [IsGraphvizGraphDigraphOrContext, IsObject]) #! then the operation fails. #! TODO I dont believe this is accurate - think it will connect existing ones #! underlying private function would fail though - TODO double check. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizAddEdge", [IsGraphvizGraphDigraphOrContext, IsObject, IsObject]); #! @Arguments graph, filter, name #! @Returns the new subgraph. #! @Description Adds a subgraph to a graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizAddSubgraph", [IsGraphvizGraphDigraphOrContext, IsObject]); DeclareOperation("GraphvizAddSubgraph", [IsGraphvizGraphDigraphOrContext]); @@ -334,6 +433,9 @@ DeclareOperation("GraphvizAddSubgraph", [IsGraphvizGraphDigraphOrContext]); #! @Arguments graph, filter, name #! @Returns the new context. #! @Description Adds a context to a graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizAddContext", [IsGraphvizGraphDigraphOrContext, IsObject]); DeclareOperation("GraphvizAddContext", [IsGraphvizGraphDigraphOrContext]); @@ -341,12 +443,18 @@ DeclareOperation("GraphvizAddContext", [IsGraphvizGraphDigraphOrContext]); #! @Arguments graph, node #! @Returns the modified graph. #! @Description Removes the node from the graph. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizRemoveNode", [IsGraphvizGraphDigraphOrContext, IsObject]); #! @Arguments graph, predicate #! @Returns the modified graph. #! @Description Filters the graph's edges using the provided predicate. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizFilterEdges", [IsGraphvizGraphDigraphOrContext, IsFunction]); @@ -354,6 +462,9 @@ DeclareOperation("GraphvizFilterEdges", #! @Returns the modified graph. #! @Description Filters the graph's edges, removing edges between nodes with #! the specified names. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizRemoveEdges", [IsGraphvizGraphDigraphOrContext, IsObject, IsObject]); @@ -366,6 +477,9 @@ DeclareOperation("GraphvizRemoveEdges", #! All current attributes remain. #! If an attribute already exists and a new value is provided, the old value #! will be overwritten. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizSetAttrs", [IsGraphvizObject, IsRecord]); DeclareOperation("GraphvizSetAttr", [IsGraphvizObject, IsObject, IsObject]); DeclareOperation("GraphvizSetAttr", [IsGraphvizObject, IsObject]); @@ -373,11 +487,18 @@ DeclareOperation("GraphvizSetAttr", [IsGraphvizObject, IsObject]); #! @Arguments obj, attr #! @Returns the modified object. #! @Description Removes an attribute from the object provided. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizRemoveAttr", [IsGraphvizObject, IsObject]); #! @Section Outputting #! @Arguments graph #! @Returns the dot representation of the graphviz object. +#! @Description TODO +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("AsString", [IsGraphvizGraphDigraphOrContext]); #! @Arguments obj @@ -385,24 +506,48 @@ DeclareOperation("AsString", [IsGraphvizGraphDigraphOrContext]); #! @Description #! Unimplemented operation which depending packages can implement. #! Should output the graphviz package representation of the object. +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("Graphviz", [IsObject]); +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizSetNodeColors", [IsGraphvizGraphDigraphOrContext, IsList]); +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("GraphvizSetNodeLabels", [IsGraphvizGraphDigraphOrContext, IsList]); -DeclareGlobalFunction("ErrorIfNotValidColor"); - # TODO doc +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("\[\]", [IsGraphvizNode, IsObject]); # TODO doc +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("\[\]\:\=", [IsGraphvizNode, IsObject, IsObject]); # TODO doc +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("\[\]", [IsGraphvizEdge, IsObject]); # TODO doc +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("\[\]\:\=", [IsGraphvizEdge, IsObject, IsObject]); # TODO doc +#! @BeginExampleSession +#! gap> +#! @EndExampleSession DeclareOperation("\[\]", [IsGraphvizGraphDigraphOrContext, IsObject]); + +DeclareGlobalFunction("ErrorIfNotValidColor"); diff --git a/gap/dot.gi b/gap/dot.gi index f3be316..6766cae 100644 --- a/gap/dot.gi +++ b/gap/dot.gi @@ -27,6 +27,9 @@ function(name) Counter := 1)); end); +InstallMethod(GraphvizGraph, "for an object", [IsObject], +obj -> GraphvizGraph(String(obj))); + InstallMethod(GraphvizGraph, "for no args", [], {} -> GraphvizGraph("")); InstallMethod(GraphvizDigraph, "for a string", [IsString], @@ -46,6 +49,9 @@ end); InstallMethod(GraphvizDigraph, "for no args", [], {} -> GraphvizDigraph("")); +InstallMethod(GraphvizDigraph, "for an object", [IsObject], +obj -> GraphvizDigraph(String(obj))); + ############################################################################# # ViewString ############################################################################# @@ -54,15 +60,7 @@ InstallMethod(PrintString, "for a graphviz node", [IsGraphvizNode], n -> StringFormatted("", GraphvizName(n))); InstallMethod(PrintString, "for a graphviz edge", [IsGraphvizEdge], -function(e) - local head, tail; - head := GraphvizHead(e); - tail := GraphvizTail(e); - - return StringFormatted("", - GraphvizName(head), - GraphvizName(tail)); -end); +e -> StringFormatted("", GraphvizName(e))); InstallMethod(PrintString, "for a graphviz (di)graph or context", [IsGraphvizGraphDigraphOrContext], diff --git a/gap/gv.gi b/gap/gv.gi index 4d52941..7cba024 100644 --- a/gap/gv.gi +++ b/gap/gv.gi @@ -147,9 +147,12 @@ InstallMethod(GV_Edge, "for two graphviz nodes", [IsGraphvizGraphDigraphOrContext, IsGraphvizNode, IsGraphvizNode], function(graph, head, tail) local out; + out := Objectify(GV_EdgeType, rec( - Name := "", + Name := StringFormatted("({}, {})", + GraphvizName(head), + GraphvizName(tail)), Head := head, Tail := tail, Attrs := GV_Map(), diff --git a/makedoc.g b/makedoc.g index 5e2725f..b18c2fe 100644 --- a/makedoc.g +++ b/makedoc.g @@ -37,7 +37,10 @@ XMLEntities.DOT := UrlEntity("DOT", XMLEntities.Graphviz := UrlEntity("Graphviz", "https://www.graphviz.org"); AutoDoc("graphviz", -rec(scaffold := rec(entities := XMLEntities), autodoc := true)); +rec(scaffold := rec(entities := XMLEntities), + autodoc := true, + extract_examples := true, +)); Unbind(PackageEntity); Unbind(UrlEntity); diff --git a/tst/testall.g b/tst/testall.g index a5ad9d1..e737bce 100644 --- a/tst/testall.g +++ b/tst/testall.g @@ -4,6 +4,6 @@ LoadPackage("graphviz"); TestDirectory(DirectoriesPackageLibrary("graphviz", "tst"), - rec(exitGAP := true)); + rec(exitGAP := true, compareFunction := "uptowhitespace")); FORCE_QUIT_GAP(1); # if we ever get here, there was an error