tikz.dev / forest Manual

Forest

Reference

3.4 The workflow

3.4.1 Stages

Forest does its job in several stages. The default course of events is the following:

  1. The bracket representation of the tree (§3.3) is parsed and stored in a data structure.

  2. The keys given in the bracket representation are processed. In detail, default preamble is processed first, then the given preamble (both in the context of the (formal) root node) and finally the keylists given to individual nodes. The latter are processed recursively, in a depth-first, parent-first fashion.

  3. Each node is typeset in its own tikzpicture environment, saved in a box and its measures are taken.

  4. The nodes of the tree are packed, i.e. the relative positions of the nodes are computed so that the nodes don’t overlap. That’s difficult. The result: option s is set for all nodes. (Sometimes, the value of l is adjusted as well.)

  5. Absolute positions, or rather, positions of the nodes relative to the root node are computed. That’s easy. The result: options x and y are set.

  6. The TikZ code that will draw the tree is produced and executed. (The nodes are drawn by using the boxes typeset in step 3.4.1.)

Stage 3.4.1 collects user input and is thus “fixed”. However, the other stages, which do the actual work, are under user’s control.

First, hooks exist between the individual stages which make it possible (and easy) to change the properties of the tree between the processing stages. For a simple example, see example (71): the manual adjustment of y can only be done after the absolute positions have been computed, so the processing of this option is deferred by before drawing tree. For a more realistic example, see the definition of style GP1: before packing, outer xsep is set to a high (user determined) value to keep the \(\times\)s uniformly spaced; before drawing the tree, the outer xsep is set to 0pt to make the arrows look better.

Second, the execution of the processing stages 3.4.1–3.4.1 is completely under user’s control. To facilitate adjusting the processing flow, the approach is twofold. The outer level: Forest initiates the processing by executing style stages, which by default executes the processing stages 3.4.1–3.4.1, preceding the execution of each but the first stage by processing the keys embedded in temporal propagators before ... (see §3.4.2). The inner level: each processing step is the sole resident of a stage-style, which makes it easy to adjust the workings of a single step. What follows is the default content of style stages, including the default content of the individual stage-styles. Both nicely readable and ready to copy-paste versions are given.

\forestset{
stages/.style={
for root'={
process keylist register=default preamble,
process keylist register=preamble
},
process keylist=given options,
process keylist=before typesetting nodes,
typeset nodes stage,
process keylist=before packing,
pack stage,
process keylist=before computing xy,
compute xy stage,
process keylist=before drawing tree,
draw tree stage
},
typeset nodes stage/.style={for root'=typeset nodes},
pack stage/.style={for root'=pack},
compute xy stage/.style={for root'=compute xy},
draw tree stage/.style={for root'=draw tree},
}

Both style stages and the individual stage-styles may be freely modified by the user. Obviously, as a style must be redefined before it is processed, stages should be redefined (using macro \ forestset) outside the forest environment; alternatively, stages can be given as the (parenthesized) optional argument of the environment (see §3.2). A stage style can also be redefined in the preamble or in any of the keylists processed prior to entering that stage.

Here’s the list of keys used either in the default processing or useful in an alternative processing flow.

  • typeset nodes(stage)

  • typeset nodes’(stage)

  • Typesets each node of the current node’s subtree in its own tikzpicture environment. The result is saved in a box (which is used later, in the draw tree stage) and its measures are taken.

    In the typeset_nodes' variant, the node box’s content is not overwritten if the box already exists.

    The order in which the nodes are typeset is controlled by nodewalk style typeset nodes processing order or, if this style is not defined, by processing order.

  • typeset node

  • Typesets the current node, saving the result in the node box.

    This key can be useful also in the default stages. If, for example, the node’s content is changed and the node retypeset just before drawing the tree, the node will be positioned as if it contained the “old” content, but have the new content: this is how the constant distance between \(\times\)s is implemented in the GP1 style.

  • pack(stage)

  • The nodes of the tree are packed, i.e. the relative positions of the nodes are computed so that the nodes don’t overlap. The result: option s is set for all nodes; sometimes (in tier alignment and for some values of calign), the value of some nodes’ l is adjusted as well.

  • pack’

  • “Non-recursive” packing: packs the children of the current node only. (Experimental, use with care, especially when combining with tier alignment.)

  • compute xy(stage)

  • Computes the positions of the nodes in the subtree relative to the current node. The results are stored into options x and y. The current node’s x and y remain unchanged.

  • draw tree(stage)

  • draw tree’(stage)

  • Produces and executes the TikZ code that draws the (sub)tree rooted in the current node.

    The procedure uses the node boxes typeset by typeset nodes or friends. The ' variant includes the node boxes in the picture using \copy, not \box, thereby preserving them.

    For details and customization, see §3.4.3.

  • draw tree box=[⟨ box⟩]

  • The picture drawn by the subsequent invocations of draw tree and draw tree’ is put into ⟨ box⟩. If the argument is omitted, the subsequent pictures are typeset normally (the default).

  • process keylist=⟨keylist option⟩

  • For each node in the entire tree, the keylist saved in ⟨keylist option⟩ of the node is processed (in the context of that node).

    Note that this key is not sensitive to the current node: it processes the keylists for the whole tree. Actually, it is possible to control which nodes are visited: ⟨keylist option⟩ processing order is walked if it is defined, otherwise processing order. In both cases, the processing nodewalk starts at the formal root of the tree (see root’ and set root), which is reevaluated at the beginning of each internal cycle (see below). By default, ⟨keylist option⟩ processing order is indeed undefined, while the processing order defauls to tree, which means that all the nodes in the entire tree are processed.

    Keylist-processing proceeds in cycles. In a given cycle, the value of option ⟨keylist option name⟩ is processed for every node visited by the processing nodewalk. During a cycle, keys may be delayed using key delay. Keys delayed in a cycle are processed in the next cycle. The number of cycles in unlimited.

    Dynamic creation of nodes happens between the cycles. The options given to the dynamically created nodes are implicitely delayed and thus processed at the end of the next cycle.

    This key is primarily intended for use within stages. The calls of this key should not be nested, and it should not be embedded under process keylist’ or process keylist register.

    When changing the processing nodewalk, note that delayed keys will be executed only for nodes visited by the processing nodewalk. Delayed spatially propagated keys will be remembered, though, and executed when the given keylist is processed for the target node. Using spatial propagators without delaying cannot result in a non-processed key.

  • process keylist’=⟨keylist option⟩⟨nodewalk⟩

  • This key is a variant of process keylist. The differences are as follows.

    The processing nodewalk is given explicitely (by ⟨nodewalk⟩) and starts at the current node (in each internal cycle).

    There is no dynamic creation of nodes between the delay cycles. Any dynamic node instructions will be remembered and executed after the next cycle of process keylist, or an explicit call to do dynamics.

    It is safe to embed this key within process keylist and (all) friends.

  • process keylist”=⟨keylist option⟩⟨nodewalk⟩

  • This key is a variant of process keylist which executes neither dynamic node operations nor delayed keys (there are thus no internal cycles). Any delayed keys will not be processed during the execution of this key. They will be remembered and executed at the end of the next cycle of process keylist or process keylist’.

    As for process keylist’, the processing nodewalk is given explicitely (by ⟨nodewalk⟩) and starts at the current node.

    It is safe to embed this key within process keylist and (all) friends.

  • process keylist register=⟨register⟩

  • Process the keylist saved in ⟨register⟩ in the context of the current node.

    Any delayed keys will not be processed during the execution of this key. They will be remembered and executed at the end of the next cycle of process keylist or process keylist’.

    It is safe to embed this key within process keylist or process keylist’.

  • processing order/.nodewalk style=⟨nodewalk⟩(nodewalk style, default tree)

  • Redefine this style to change the default order in which process keylist processes a keylist option. For example, to process the nodes in a child-first fashion, write

    processing order/.nodewalk style=tree children first

    Note that this is a nodewalk style, so it must be defined either using .style handler during a nodewalk or using .nodewalk style.

  • ⟨keylist option⟩ processing order/.nodewalk style=⟨nodewalk⟩(nodewalk style, default processing order)

  • Redefine this style to change the process keylist processing order for a specific ⟨keylist option⟩. For example, to process before drawing tree options in the child-first fashion, leaving the processing of other before ... keylists untouched, write

    before drawing tree processing order/.nodewalk style=tree children first
3.4.2 Temporal propagators

Temporal propagators delay processing of given keys until some other point in the processing of the tree. There are three kinds of temporal propagators. Most of the propagators have the form before_... and defer the processing of the given keys to a hook just before some stage in the workflow (§3.4.1). before packing node and after packing node are special as they fire during the packing stage. The delay propagator is “internal” to the current hook: the keys in the hook are processed cyclically, and delay delays the processing of the given keys until the next cycle.

Formally, temporal propagators are keylist options (except delay n, which is a style), so augmented assignments are possible (§3.6.1).

All temporal propagators can be nested without limit.

  • A note on typos.

    By default, all keys unknown to Forest are appended to keylist option node options The value of node options is fed to TikZ when typesetting a node, so any typos are caught by TikZ. However, as nodes are normally typeset in stage typeset nodes stage, any typos in keys temporally propagated past that stage will not be noticed, simply because noone will use the value of node options where they end up (the exception being nodes which are explicitely retypeset by the user using typeset node).

    To sum up, typos in any keys temporally propagated by before packing, before packing node, after packing node, before computing xy and before drawing tree will be silently ignored. This is probably not what you want, so double-check everything you write there.

    Using unknown to=unknown key error, it is possible to change the default behaviour. You will catch all typos if you append the command to pack stage, as shown below. This can be done either in the tree or by \ forestset.

    typeset nodes stage/.append style={unknown to=unknown key error}

    Of course, this makes it impossible to write simply before_drawing_tree={inner_sep=5pt,_typeset_node}. Any tikz’s options must be given explicitely via node options: before_drawing_tree={node_options={inner_sep=5pt},_typeset_node}.

  • delay=⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ until the next cycle.

    Internally, delay is a keylist option, so augmented operators of the ⟨keylist⟩ type can be used.

    To check whether any keys were delayed, use conditional if have delayed.

  • delay n=⟨integer⟩⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ for \(n\) cycles. \(n\) may be \(0\), and it may be given as a pgfmath expression.

  • given options(propagator)

  • When stages processing starts, this list holds the keys given by the user in the bracket representation.

  • before typesetting nodes=⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ to until just before the nodes are typeset.

  • before packing=⟨keylist⟩(propagator)

  • before packing node=⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ given to the node to until just before/after the subtree of this specific node is packed. Even before packing node, the (subtrees of the) children of the node have already been packed.1

  • after packing node=⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ given to the node to until just after this specific node is packed.

    (54)

    Compiled output

    \forestset{box/.style={
    draw, no edge, l=0, l sep=1.5ex,
    calign=first, anchor=base west,
    content format={\strut\forestoption{content}},
    if n children=0{}{
    ~after packing node~={
    minimum width/.pgfmath=
    {s("!l")+max_x("!l")-s("!1")-min_x("!1")},
    for children/.wrap pgfmath arg={s+={##1}}{0},
    typeset node}}}}
    \begin{forest} for tree={box} [/
    [home[saso[Download][TeX]][alja][joe]]
    [usr[bin][share]]]
    \end{forest}
    • Remember to typeset or pack the node using pack’ if you have changed options influencing the typesetting or packing process.

  • before computing xy=⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ to until just before the absolute positions of the nodes are computed.

  • before drawing tree=⟨keylist⟩(propagator)

  • Defers the processing of the ⟨keylist⟩ to until just before the tree is drawn.

3.4.3 Drawing the tree

This section provides a detailed description of how draw tree and friends draw the tree.

First, here’s the default course of events. draw tree is called from style draw tree stage in the context of the formal root node. It does not draw the tree directly, but rather produces TikZ code that actually does the drawing. The tree-drawing instructions are enclosed in a tikzpicture environment and come in three parts: the (non-phantom) nodes are drawn first, followed by edges between the drawn nodes and finally the custom TikZ code (of all, including phantom nodes). Each of those is drawn for the entire (sub)tree of the current node, in recursive, depth-first parent-first first-child-first order.

Most parts of the tree drawing procedure are customizable. Zooming in from the invocation of draw tree to the keys that produce the drawing code, the customization options are as follows.

There are two ways the invocation of draw tree can differ from the default. First, draw tree can be called within the context of any node. As a first approximation, that node will become the root of the tree that is being drawn; for the whole truth, see draw tree method. Second, draw tree can be called not only at draw tree stage, but any time after the nodes to be drawn have been typeset (see typeset nodes stage) and their absolute coordinates (x and y) computed (see compute xy stage).

  • begin draw/.code=⟨toks: code⟩(default \begin {tikzpicture})

  • (tikzpicture)node key>end draw/.code=⟨toks: code⟩

    The code produced by draw tree is put in the environment specified by begin draw and end draw. Thus, it is this environment, normally a tikzpicture, that does the actual drawing.

    A common use of these keys might be to enclose the tikzpicture environment in a center environment, thereby automatically centering all trees; or, to provide the TikZ code to execute at the beginning and/or end of the picture.

    Note that begin draw and end draw are not node options: they are \pgfkeys’ code-storing keys [Tantau 2007, §55.4.3–4].

Repeating from (§3.4.1), there are two variants of draw tree, which differ in how they use the node boxes created by typeset nodes: draw tree includes them using \box, so they are gone; draw tree’ uses \copy, so they are preserved. Next, setting draw tree box will cause the tree to be drawn in the given box.

  • draw tree method(style)

  • This is the heart of the tree-drawing procedure: it determines which parts of the tree are drawn and in what order. What this style does by default was already described above, but is actually best seen from the definition itself:

    draw tree method/.style={
    for nodewalk={
    draw tree nodes processing order/.try,
    draw tree processing order/.retry,
    processing order/.lastretry
    }{draw tree node},
    for nodewalk={
    draw tree edges processing order/.try,
    draw tree processing order/.retry,
    processing order/.lastretry
    }{draw tree edge},
    for nodewalk={
    draw tree tikz processing order/.try,
    draw tree processing order/.retry,
    processing order/.lastretry
    }{draw tree tikz}
    },

    This style may be modified by the user, but it is and should be invoked only within draw tree, by the package: do not execute this style directly!

    The nodewalks occurring in the default definition of this style are, with the exception of processing order, not used anywhere else in the package.

  • draw tree nodes processing order(nodewalk style)

  • draw tree edges processing order(nodewalk style)

  • draw tree tikz processing order(nodewalk style)

  • For each of these nodewalk styles the following holds. If it is defined, it determines which nodes / edges / pieces of tikz code are drawn and in which order. If any of these styles is not defined, its function is taken over by draw tree processing order. By default, none of them are defined.

  • draw tree processing order(nodewalk style)

  • If this nodewalk is defined, it functions as a fallback for node-, edge- and tikz-code-specific nodewalks. If it is not defined (the default situation), it has its own fallback: processing order (which defaults to tree).

  • draw tree node

  • draw tree node’

  • Draws the current node at location specified by x and y. The ' variant draws the node even if it’s phantom.

    These keys should only be used only within the definition of draw tree method.

  • if node drawn=⟨nodewalk⟩⟨true keylist⟩⟨false keylist⟩(conditional)

  • Execute ⟨true keylist⟩ if the node at the end of ⟨nodewalk⟩ was already drawn in the current invocation of draw tree; otherwise, execute ⟨false keylist⟩.

  • draw tree edge

  • draw tree edge’

  • Draws the edge from the current node to its parent, using the information in edge path and edge.

    The variant without ' variant tries to be smart: it draws the edge only if both the current node and its parent have been drawn in the current invocation of draw tree. (This prevents drawing the edge from the root node and edges from or to phantom nodes.) The ' variant is dumb.

    These keys should only be used only within the definition of draw tree method.

  • draw tree tikz(style, default draw tree tikz')

  • draw tree tikz’

  • Executes the custom code stored in option tikz of the current node.

    By default, both keys execute the code without performing any checks. Specifically, tikz code of phantom nodes is executed. To change this behaviour easily, the user can redefine draw tree tikz, which is a style; probably, the definition will employ draw tree tikz’. For example, to execute tikz code only if the node is not phantom, write

    draw tree tikz/.style={if phantom={draw tree tikz'}{}}

    These keys should only be used only within the definition of draw tree method.

1 Forest employs two variants of the packing algorithm: the faster one is used for (parts of) trees with uniform growth, i.e. subtrees where grow does not change; the slower, generic variant is used in where this is not the case. Now, the fast method works by dealing with l and s dimension separately, and it is able to do this for the entire (sub)tree, without needing to invoke the packing method for its constituents. The consequence is that there is no place where before packing node could be called meaningfully, as the node’s constituents are not packed individually, “just before packing the current node” is the same as “just before packing the tree”, and for many nodes packing is not called anyway in the fast method. As the rationale behind before packing node is to be able to adjust the options of the subtree based on the information gained by packing its constituents, specifying before packing node automatically switches to the generic method.