Graph::Easy - Manual

Syntax

If you haven't done so, please read the Overview first.

This chapter describes the syntax of the text format that is parsed by Graph::Easy::Parser into a Graph::Easy object.

General rules

Input and Encoding

Graph::Easy, and especially the Parser, expect the input to be in utf-8. This means that the input must be valid Unicode.
But it also means you can embed arbitrary characters, like Japanese, box art drawing, Umlaute etc. into the labels without the need for cumbersome quoting.

Comments

Comments start with a # character and run til the end of the line.
Certain things are except from this rule, like color values like #ff00aa inside attributes, where the '#' will not start a comment.

To make sure that you comments are parsed correctly, always put a space as the first character after the hatch (entire lines consisting only of the '#' character are ok, though):

############################
# This is a good comment.

#############################
#This is bad.

Whitespace

Whitespace does generally not matter, e.g. multiple spaces are collapsed together to one, and linebreaks are ignored. Whitespace at the front and end of label texts is removed, likewise. Thus the following two are equivalent:

[A]->[B][C]->[D]
[ A ] -> [ B ]
[ C ] -> [ D ]

When writing graph text, you are encouraged to use whitespace and linebreaks for clarity, like in the second example above.

To insert a line break into a node or edge label, use literally \n:

[ My\n long\n node\n name ] -- A\n long\n label --> [ B ]
+------+          +---+
| My   |  A       |   |
| long |  long    | B |
| node |  label   |   |
| name | -------> |   |
+------+          +---+

You can also replace the \n by \r, \c or \l to align the next line right, left or center, respectively:

[ Long Node Label\l left\r right\c center ] -- A\r long\n edge label --> [ B ]
+-----------------+               +---+
| Long Node Label |  A            |   |
| left            |        long   | B |
|           right |  edge label   |   |
|     center      | ------------> |   |
+-----------------+               +---+

Nodes

Nodes are written (or "quoted", if you wish) with enclosing square brackets:

[ Single node ]
[ Node A ] --> [ Node B ]

You can also have a list of nodes by separating them with a comma:

[ A ], [ B ], [ C ] --> [ D ]
+---+     +---+     +---+
| A | --> | D | <-- | C |
+---+     +---+     +---+
            ^
            |
            |
          +---+
          | B |
          +---+

It also works for lists on the right side of an edge:

[ A ] -> [ B ], [ C ], [ D ]
+---+     +---+     +---+
| B | <-- | A | --> | C |
+---+     +---+     +---+
            |
            |
            v
          +---+
          | D |
          +---+

In addition, you can chain nodes together like this:

[ A ] -> [ B ] -> [ C ]
 -> [ D ]
 -> [ E ]

You can also create invisible, anonymous nodes with [ ]. These nodes are called anonymous, because you do not know their name and thus cannot refer to them again:

[ ] -> [ Karlsruhe ] -> [ ] -> [ Plauen ]

That would be rendered like:

        +-----------+             +--------+
    --> | Karlsruhe | -->     --> | Plauen |
        +-----------+             +--------+

If you merely want an invisible node, use either shape: invisible; (for a node with a certain minimum size) or shape: point; point-style: invisible; for a very small and invisible node:

[ $sys$Node ] { shape: invisible; title: You don't see me! }
  -> [ Bischofswerda ]
  -> [ Borna ] { shape: point; point-style: invisible; }
  -> [ Bremen ]
  -> [ $sys$Node ]

  +------------------------------------+
  v                                    |
          +---------------+          +--------+
      --> | Bischofswerda | -->  --> | Bremen |
          +---------------+          +--------+

Attributes

Attributes are enclosed in { }, are in the format attributename: attributevalue;.

Attributes names must not be quoted, attribute values can be quoted, and the quotes will be removed on them:

[ "Monitor Size" ] --> { label: 21"; } [ Big ] { label: "Huge"; }
This will produce:


If you want to embed a ; (semi-colon), then quote the string:

[ Baz;Bar ] --> { label: "Baz;Bar"; } [ Berlin ] { label: ";;"; }

If you want to embed a semi-colon and have quotes at the start and end of the string value, then use backslashes to escape the quotes and encode the semi-colon as %3b:

[ A ] { label: \"Hello%3b\"; } --> [ Berlin ] { label: Baz%3bBar; }

Note that the need to code, encode or escape B apply to attribute values, and not to node or group names, since these are always used as-they-are.

Attributes follow immidiately the object(s) for that they apply.
Please note that attributes following a node in a node list apply to all nodes in the list that came to this point.

graph { background: white; }	# for the graph itself
node { background: white; }	# for all nodes
edge { style: bold; }		# for all edges
node.city { background: red; }	# for all nodes with class "city"

[ Bonn ] { class: city; }	# for the node "Bonn"

[ Bonn ] --> { style: dotted; }	# for the edge "Bonn" to "Berlin"
[ Berlin ] { color: green; }	# for the node "Berlin"

[ ABC ] { border: bold; color: white; }

[ DEF ] 			# DEF has not yet attributes
  {
  fill: #ff8060;		# applies only to DEF
  } ,
[ GHI ]
  {				# these apply to DEF and GHI!
    border: bold; 
    color: white; 
  } ,
[ JKL ]
  {
    shape: circle;		# apply to DEF, GHI and JKL
  }

[ ] { fill: brown; }		# for the anonymous node only

As a special case for autosplit nodes, you can separate attribute values with "|" (vertical bar) for each part of the auto-split node:

[ Bonn | Berlin | Frankfurt ] { fill: red|yellow|blue; }

In the example above, "Bonn" would be red, "Berlin" yellow and "Frankfurt" blue. Missing values will not set the attribute on the node as in the following example, where "Berlin" and "Ulm" will get the default background (white):

node { fill: white; }

[ Bonn | Berlin | Hahn | Ulm ] { fill: red||blue; }

You can also set an attribute for all parts, or only for specific parts:

Here are the rules from above in an example showing their effect:

node.1 { border: dotted; }
node.2 { border: dashed; }
node.3 { border: dot-dash; }
node { border: double; }

[ AAAA|BBBB ] { class: |1; }
[ CCCC|DDDD ] { class: 2|; }
[ EEEE|FFFF ] { class: 3; }
#======#.......
H AAAA H BBBB :
#======#......:
+ - - -+======#
' CCCC ' DDDD H
+ - - -+======#
+-.-.-.+.-.-.-+
! EEEE ! FFFF !
+-.-.-.+.-.-.-+

For a complete listing of possible attributes see the appropriate chapter.

Edges

The edges between the nodes can have the following styles:

        ->              solid
        =>              double
        .>              dotted
        ~>              wave

        - >             dashed
        .->             dot-dash
        ..->            dot-dot-dash
        = >             double-dash

In addition to these, the following styles exist:

Unlike the normal edge styles, these can only be set via the (optional) edge attributes:

        [ A ] --> { style: bold; }      [ B ]
              --> { style: broad; }     [ B ]
              --> { style: bold-dash; } [ C ]
              --> { style: invisible; } [ D ]
            ####
            v  #
+---+     +------+     +---+     +---+
| A | ##> |  B   | # > | C |     | D |
+---+     +------+     +---+     +---+

You can repeat each of the style-patterns as much as you like:

        --->
        ==>
        =>
        ~~~~~>
        ..-..-..->

Note that in patterns longer than one character, the entire pattern must be repeated e.g. all characters of the pattern must be present. Thus:

        ..-..-..->      # valid dot-dot-dash
        ..-..-..>       # invalid!

        .-.-.->         # valid dot-dash
        .-.->           # invalid!

In additon to the styles, the following two directions are possible:

         --             edge without arrow heads
         -->            arrow at target node (end point)
        <-->            arrow on both the source and target node
                        (end and start point)

Of course you can combine all directions with all styles. However, note that edges without arrows cannot use the shortcuts for styles:

        ---             # valid
        .-.-            # valid
        .-              # invalid!
        -               # invalid!
        ~               # invalid!

Just remember to use at least two repetitions of the full pattern for arrow-less edges.

You can also give edges a label, either by inlining it into the style, or by setting it via the attributes:

        [ AB ] --> { style: bold; label: foo; } [ ABC ]
        -- foo -->
        ... baz ...>

        -- solid -->
        == double ==>
        .. dotted ..>
        ~~ wave ~~>

        -  dashed - >
        =  double-dash = >
        .- dot-dash .->
        ..- dot-dot-dash ..->

Note that the two patterns on the left and right of the label must be the same, and that there is a mandatory space between the left pattern and the label, as well as the label and the right pattern.

You may use inline labels only with edges that have at least one arrow. Thus:

        <-- label -->   # valid
        -- label -->    # valid

        -- label --     # invalid!

To use a label with an edge without arrow heads, use the attributes:

        [ AB ] -- { label: edgelabel; } [ CD ]

For a complete listing of possible edge attributes see the appropriate chapter.

Groups

You can group nodes together by using parantheses:

( German Cities
  [ Berlin ] -> [ Potsdam ]
) { 
  background: lightbrown;
  }

Putting nodes into a group gives the layouter the hint that these nodes are related and should be laid out closely together. The name of the group can also be ommitted. Since the group label defaults to the group name you will get an invisible label as a side-effect:

( [ Bremen ] -> [ Bremerhaven ] )
+ - - - - - - - - - - - - - - - -+
'                                '
' +--------+     +-------------+ '
' | Bremen | --> | Bremerhaven | '
' +--------+     +-------------+ '
'                                '
+ - - - - - - - - - - - - - - - -+

Please see the section about grouping for further details and examples.

Advanced Layouts

Joints

Sometimes you want on edge join another, or have a pair of edges start at a common point, and then split up. Or you even want two edges being connected by a third edge. Graph::Easy allows all these things by a feature called shared ports.

For detailed information and examples please see the chapter about joints.

Classes

Each part of a graph is a (primary) class and you can set attributes on a per-class basis:

graph { color: red; }
edge { color: blue; }
node { color: green; }
group { color: brown; }

All objects in a graph automatically belong to their primary class, e.g. nodes are in the class "node". Except graph, all primary classes can have subclasses:

edge { color: blue; }
edge.train { color: darkblue; }
node { color: green; }
node.cities { color: darkgreen; }
group { color: brown; }
group.cities { color: darkbrown; }

See also the section about class names for reference.

Relative placement (via auto-split)

You can cluster nodes together by placing them relatively to each other.
Perhaps the easiest way to achive the placement is to use the auto-split feature:

Please see the section in Hinting for examples and explanations.