Graph::Easy - Manual - Syntax

# 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

#### 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 | -------> |   |
    +------+          +---+

#### 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 seperating them with a comma:

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

Node lists currently only work on the left side of an expression.

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 `shape: invisible;`:

    [ You don't see me! ] { shape: invisible; } -> [ Bischofswerda ]
    -> [ You don't see me! ]

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

#### Attributes

Attributes are enclosed in `{ }`, are in the format `attributename: attributevalue;` and follow immidiately the object for that they apply.

    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 ]
      {
        border: bold;
        color: white;
      }

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

There is also the style "bold". Unlike the others, this can only be set via the (optional) edge attributes:

            [ A ] --> { style: bold; } [ B ]

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 attributes see the appropriate chapter.

### Advanced Layouts

#### Classes

Each part of a graph is a (primary) class and you can assign it attributes:

    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; }

#### Groups

You can group nodes together by using braces:

    ( 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.

This is especially powerfull in combintation with the `nodeclass` attribute:

    node.cities { color: blue; }

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

In this example, all nodes in the group will automatically be put into the class `node.cities`.

#### 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:

- a `|` (vertical bar) in the node name will split the node into two parts, and place them next to each other, horizontally
- likewise, `||` (two vertical bars) in the node name will split the node into two parts, but place the second part at the start of a new row

Here is a few examples to make this clear:

    [ A | B | C ]

    +---+---+---+
    | A | B | C |
    +---+---+---+

    [ A | B || C ]

    +---+---+
    | A | B |
    +---+---+
    | C |
    +---+

    [ A | B ||
      C | D | E ||
      F ]

    +---+---+
    | A | B |
    +---+---+---+
    | C | D | E |
    +---+---+---+
    | F |
    +---+

- If a part between two `|` consists of exactly one space, an invisible cell will be generated, e.g. one without borders and background
- If a part between two `|` consists of more than one space, an empty cell (e.g. with borders and background) will be generated

    [ A | | B || C | | D |   | E ]

    +---+   +---+
    | A |   | B |
    +---+   +---+---+---+
    | C |   | D |   | E |
    +---+   +---+---+---+

#### Relative placement - manually

Another way is to specify an `origin` and `offset` for a node, placing it relatively to another node:

    [ Left ] -> [ Right ] { origin: Left; offset: 2,1; }

    +------+
    | Left |
    +------+
      |
      |              +-------+
      +------------> | Right |
                     +-------+

The offset should not be `0,0`. Also, be carefull to node place nodes inside each other, especially when using multicelled nodes as explained below.

You can set an origin for each node, even if this node has an origin itself. The only exception is that you may not create loops like in the following:

    [ A ] { origin: B; offset: 1,1; }
    [ B ] { origin: A; offset: 1,1; }	# invalid!

    [ C ] { origin: E; offset: 1,1; }
    [ D ] { origin: C; offset: 1,1; }
    [ E ] { origin: C; offset: 1,1; }	# invalid!

Here is an example, using a chain of origins:

    [ A ] { origin: B; offset: 2,1; }

    -> [ B ] { origin: C; offset: 1,1; }
    -> [ C ] { origin: D; offset: 1,1; }
    -> [ D ]
    -> [ E ]

    +---+     +---+
    | D | --> | E |
    +---+     +---+
      ^  +---+
      +--| C |
         +---+
           ^  +---+
           +--| B |
              +---+
                ^       +---+
                +------ | A |
                        +---+

#### Multi-celled nodes

You can specify the size of a node in rows and columns by using either the `rows`, `columns` or `size` attribute:

    [ A ] { size: 2,2; }
    -> [ B ] { rows: 2; }
    -> [ C ] { columns: 3; }

Here is an example that demonstrates this:

    [ A ] { size: 2,2; }
    -> [ B ] { rows: 2; }
    -> [ C ] { columns: 3; }

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

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

    [ A ] -> [ F ]
    [ A ] -> [ G ]

           +---------+
           |         v
         +---+     +-------------+     +---+
         |   | --> |      C      | --> | D |
         | B |     +-------------+     +---+
         |   |       ^         ^         |
      +->|   | ------+         +---------+
      |  +---+
      |    ^
      |    |
      |    |
      |  +--------+     +---+
      +--|        | --> | F |
         |   A    |     +---+
         |        |     |   |
         |        | --> | G |
         +--------+     +---+

Please continue with the chapter about the attributes.