texlive[42640] Master/texmf-dist: forest (5dec16)
commits+karl at tug.org
commits+karl at tug.org
Tue Dec 6 01:28:11 CET 2016
Revision: 42640
http://tug.org/svn/texlive?view=revision&revision=42640
Author: karl
Date: 2016-12-06 01:28:11 +0100 (Tue, 06 Dec 2016)
Log Message:
-----------
forest (5dec16)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/forest/README
trunk/Master/texmf-dist/doc/latex/forest/forest-doc.pdf
trunk/Master/texmf-dist/doc/latex/forest/forest-doc.tex
trunk/Master/texmf-dist/doc/latex/forest/forest.pdf
trunk/Master/texmf-dist/source/latex/forest/forest-index.dtx
trunk/Master/texmf-dist/source/latex/forest/forest-libs.dtx
trunk/Master/texmf-dist/source/latex/forest/forest.dtx
trunk/Master/texmf-dist/tex/latex/forest/forest-compat.sty
trunk/Master/texmf-dist/tex/latex/forest/forest-doc.sty
trunk/Master/texmf-dist/tex/latex/forest/forest-index.sty
trunk/Master/texmf-dist/tex/latex/forest/forest-lib-edges.sty
trunk/Master/texmf-dist/tex/latex/forest/forest-lib-linguistics.sty
trunk/Master/texmf-dist/tex/latex/forest/forest.sty
Modified: trunk/Master/texmf-dist/doc/latex/forest/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/forest/README 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/doc/latex/forest/README 2016-12-06 00:28:11 UTC (rev 42640)
@@ -1,4 +1,4 @@
-LaTeX package: forest [2016/04/09 v2.0.3 Drawing (linguistic) trees]
+LaTeX package: forest [2016/12/05 v2.1 Drawing (linguistic) trees]
Copyright (c) 2016 Saso Zivanovic
(Sa\v{s}o \v{Z}ivanovi\'{c})
Modified: trunk/Master/texmf-dist/doc/latex/forest/forest-doc.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/forest/forest-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/forest/forest-doc.tex 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/doc/latex/forest/forest-doc.tex 2016-12-06 00:28:11 UTC (rev 42640)
@@ -1,7 +1,7 @@
%% forest-doc.tex
%% `forest-doc.tex` is a main documentation source of package `forest`.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -29,7 +29,7 @@
nohead
]{geometry}
-%\immediate\write18{makeindex -s forest-doc.ist forest-doc}
+\immediate\write18{makeindex -s forest-doc.ist forest-doc}
\def\indexlettertotoc#1\relax{%
\phantomsection\addcontentsline{toc}{subsection}{#1}%
#1%
@@ -55,6 +55,23 @@
}
\usepackage{forest-doc}
+% \usepackage{patchpgf}
+% \newcommand\pgfprofilenewforcommandcs[2]{%
+% \expandafter\pgfprofilenewforcommand\expandafter{\csname #1\endcsname}{#2}}
+% \newcommand\pgfprofilenewforpgfkey[1]{%
+% \edef\marshal{%
+% \noexpand\pgfprofilenewforcommandpattern[#1]{\expandonce{\csname pgfk@#1/. at cmd\endcsname}}{####1\noexpand\pgfeov}{####1\noexpand\pgfeov}
+% }\marshal
+% }
+% \usetikzlibrary{profiler}
+% \makeatletter
+% \pgfprofilenewforcommand{\forestindex at index}{3}
+% \pgfprofilenewforcommand{\pgfmathparse}{1}
+% \pgfprofilenewforpgfkey{/forest/split}
+% \pgfprofilenewforpgfkey{/forest/nodewalk/reverse}
+% \pgfprofilenewforcommand{\forest at Nodewalk}{2}
+% \pgfprofilenewforcommand{\pgfkeysalso}{1}
+% \makeatother
\usepackage{hyperref}
\hypersetup{unicode=true,colorlinks=true,linkcolor=blue,citecolor=blue,hyperindex=false}
@@ -100,11 +117,11 @@
if index entry type={definition}{
temptoksa/.register=result,
hyper,
- result/.wrap 2 pgfmath args={%
+ result/.process=ROw2{result}{argument}{%
\texttt{\string\begin\char`\{##1\char`\}}%
- \forestoption{argument}%
- \texttt{\string\end\char`\{##2\char`\}}%
- }{result}{temptoksa},
+ ##2%
+ \texttt{\string\end\char`\{##1\char`\}}%
+ }
}{
hyper
}
@@ -186,7 +203,7 @@
>{aggregate}
\indexset
- [form={\texttt{pgfmath} function},for first={format={pgfkey}}]
+ [form={\texttt{pgfmath} function},for first={format={detokenize,pgfkey}}]
>{pgfmath}
\indexset
@@ -197,9 +214,9 @@
form={},
for first={
for first={
- key+/.pgfmath=argument("!parent"),
+ key+/.option=!parent.argument,
index format={
- result+/.wrap pgfmath arg={\protect\meta{##1 option}}{argument("!parent")}
+ result+/.process={Ow1} {!parent.argument} {\protect\meta{##1 option}},
},
print format={
if argument={}{}{
@@ -217,9 +234,9 @@
form={},
for first={
for first={
- +key/.pgfmath=argument("!parent"),
+ +key/.option=!parent.argument,
index format={
- +result/.wrap pgfmath arg={\protect\meta{##1 option}}{argument("!parent")}
+ +result/.process={Ow1} {!parent.argument} {\protect\meta{##1 option}},
},
print format={
if argument={}{}{
@@ -237,10 +254,9 @@
form={},
for first={
for first={
- key/.wrap 2 pgfmath args={##1 ##2}{key}{argument("!parent,parent")},
+ key/.process={OOw2} {key} {!parent,parent.argument} {##1 ##2},
index format={
- result+={\space},
- result+/.wrap pgfmath arg={\protect\meta{##1}}{argument("!parent,parent")}
+ result+/.process={Ow1} {!parent,parent.argument} {\space\protect\meta{##1}},
},
print format={
if argument={}{}{
@@ -259,10 +275,9 @@
form={},
for first={
for first={
- key/.wrap 2 pgfmath args={##2 ##1}{key}{argument("!parent,parent")},
+ key/.process={OOw2} {key} {!parent,parent.argument} {##2 ##1},
index format={
- +result={\space},
- +result/.wrap pgfmath arg={\protect\meta{##1}}{argument("!parent,parent")}
+ +result/.process={Ow1} {!parent,parent.argument} {\protect\meta{##1}\space},
},
print format={
if argument={}{}{
@@ -281,7 +296,7 @@
index key format={result/.expanded=\forestoption{argument} value},
format={result/.expanded=\noexpand\texttt{\forestoption{argument}} value},
for first={format=pgfkey}
- ]>{value}
+ ]>{value of}
\indexset[
index key format={result/.expanded=\forestoption{argument} option},
@@ -290,8 +305,13 @@
]>{option of}
\indexset
- [form={},for first={format=meta}]
- >{meta}
+ [form={},for first={
+ print format={if argument={}{}{
+ result+={:\ },
+ result+/.option=argument,
+ }},
+ format=meta,
+ }]>{meta}
\indexset[
for first={+key={{cs }},format={pgfkey}}
@@ -305,6 +325,10 @@
[for first={format=pgfkey}]
>{named nodewalk}
+\indexset[
+ format={result/.expanded=\noexpand\texttt{process instruction}},
+ for first={format=pgfkey}
+ ]>{processor}
{\makeatletter % an dirty patch: \lst at nolig can sneak in the name...
\gdef\myexampleindex#1{{\def\lst at nolig{}\lstaspectindex{#1}{}}}
@@ -329,7 +353,7 @@
web:
\href{http://spj.ff.uni-lj.si/zivanovic/}{http://spj.ff.uni-lj.si/zivanovic/}}}
-%\usepackage[trace]{trace-pgfkeys} % silent, stack, trace, verbose
+%\usepackage[verbose]{trace-pgfkeys} % silent, stack, trace, verbose
%\pgfkeystracelevel{trace}
\begin{document}
@@ -338,6 +362,7 @@
% short verbatim: | (changes spaces into _)
\DeleteShortVerb\|
+\def\indexpipe{|}
{\catcode`\_=12 \def\marshal{%
\lstMakeShortInline[basicstyle=\ttfamily,literate={_}{ }1 {__}{_}1]}%
\expandafter}\marshal |
@@ -368,7 +393,7 @@
\vspace{1cm}
-\begin{forestexample}[basicstyle=\ttfamily\scriptsize,layout=tree on top,no label,v sep=1cm,index={content,pgfmath,propagator>if,repeat,append,before drawing tree,y,alias,for step,step>children,edge,before typesetting nodes,tree,s sep,dimen+,l,ancestors,typeset node,nodewalk,readonly option>level,sort by,step>min}]
+\begin{forestexample}[basicstyle=\ttfamily\scriptsize,layout=tree on top,no label,v sep=1cm,index={content,pgfmath,conditional>if,repeat,append,before drawing tree,y,alias,for step,step>children,edge,before typesetting nodes,tree,s sep,dimen+,option>l,ancestors,typeset node,nodewalk,readonly option>level,sort by,step>min}]
\pgfmathsetseed{14285}
\begin{forest}
random tree/.style n args={3}{% #1 = max levels, #2 = max children, #3 = max content
@@ -444,9 +469,14 @@
\section{Tutorial}
\label{sec:tutorial}
-This short tutorial progresses from basic through useful to
-obscure \dots
+This short tutorial progresses from basic through useful to obscure \dots fortunately, it is not the
+only newcomer's source of information on \foRest;: check out
+\href{http://mirrors.ctan.org/info/forest-quickstart/ForestQuickstart.pdf}{Forest Quickstart Guide
+ for Linguists}. Another very useful source of information (and help!) about \foRest; and \TeX\ in
+general is \href{http://tex.stackexchange.com}{\TeX\ StackExchange}. Check out the questions tagged
+\href{http://tex.stackexchange.com/questions/tagged/forest}{\texttt{forest}}!
+
\subsection{Basic usage}
\label{tut:basic-usage}
@@ -529,6 +559,7 @@
writing its name before the first (opening) bracket of the tree.
\begin{forestexample}[label=ex:gp1-frost,code prefix={\def\usepackage[##1]##2{}}]
\usepackage[~linguistics~]{forest}
+ % ...
\begin{forest} ~GP1~ [
[O[x[f]][x[r]]]
[R[N[x[o]]][x[s]]]
@@ -545,9 +576,6 @@
more information on loading libraries, see \S\ref{ref:package-options}.
-(Style \index{GP1} used above is defined in the \keyname{linguistics}
-library of the \foRest; package.)
-
\subsection{Options}
\label{tut:options}
@@ -556,7 +584,7 @@
section~\ref{tut:basic-usage}, we have seen that the \index{GP1} style
vertically aligns the parent with the first
child. This is achieved by setting option \index{calign} (for
-\emph{c}hild-\emph{align}ment) to \index{value=calign>first} (child).
+\emph{c}hild-\emph{align}ment) to \index{value of=calign>first} (child).
Let's try. Options are given inside the brackets, following the
content, but separated from it by a comma. (If multiple options are
@@ -564,7 +592,7 @@
assignment takes the form \meta{option name}|=|\meta{option value}. (There are
also options which do not require a value or have a default value:
these are given simply as \meta{option name}.)
-\begin{forestexample}[label=ex:numerals-simple,index={calign,value=calign>first}]
+\begin{forestexample}[label=ex:numerals-simple,index={calign,value of=align>first}]
\begin{forest}
[\LaTeX\ numerals, ~calign=first~
[arabic[1][2][3][4]]
@@ -575,7 +603,7 @@
\end{forestexample}
The experiment has succeeded only partially. The root node's
-children are aligned as desired (so \index{calign}|=|\index{value=calign>first} applied to the
+children are aligned as desired (so \index{calign}|=|\index{value of=calign>first} applied to the
root node), but the value of the \index{calign} option didn't get
automatically assigned to the root's children! \emph{An option given
at some node applies only to that node.} In \foRest;, the options
@@ -593,9 +621,9 @@
]
\end{forest}
\end{forestexample}
-The value of propagator \index{for step=\index{tree}} is the option string that we
-want to process. This option string is propagated to all the nodes in
-the subtree\footnote{It might be more precise to call this option
+The value of propagator \index{for step=\index{tree}} is a list of keys that we
+want to process. This keylist is propagated to all the nodes in
+the subtree\footnote{It might be more precise to call \index{for step=\index{tree}}
\texttt{for subtree} \dots\@ but this name at least saves some typing.}
rooted in the current node (i.e.\ the node where \index{for step=\index{tree}} was
given), including the node itself. (Propagator \index{for step=\index{descendants}} is
@@ -657,7 +685,8 @@
\TeX\ command |\romannumeral|. To change the content of the node,
we use option \index{content}. When specifying its new value, we can use
|#1| to insert the current content.\footnote{This mechanism is called
-\emph{wrapping}. \index{content} is the only option where wrapping works implicitely (simply
+ \emph{wrapping}. By default, \index{content} is the only \index{autowrapped toks} option,
+ i.e.\ option where wrapping works implicitely (simply
because I assume that wrapping will be almost exclusively used with this option). To wrap values
of other options, use handler \index{wrap value}; see~\S\ref{ref:handlers}.}
\begin{forestexample}[point={content,delay},index={for step,step>children,content,delay},label=ex:romannumeral]
@@ -671,8 +700,8 @@
would get arabic numerals. This is so because of the order in which the options are processed.
First, the processing proceeds through the tree in a depth-first, parent-first fashion (first the
parent is processed, and then its children, recursively; but see \index{processing order}). Next,
-the option string of a node is processed linearly, in the order they were given. (Option
-\index{content} is specified implicitely and is always the first.) If a propagator is encountered,
+the option string of a node is processed linearly, in the order they were given. Option
+\index{content} is specified implicitely and is always the first. If a propagator is encountered,
the options given as its value are propagated \emph{immediately}. The net effect is that if the
above example contained simply |roman,for_children={content=...}|, the \index{content} option
given there would be processed \emph{before} the implicit content options given to the children
@@ -687,19 +716,19 @@
spatial, but a temporal propagator. Several other temporal propagators options exist, see
\S\ref{ref:stages}.
-We are now ready to learn about simple conditionals. Every node option has the corresponding
-\index{if option=\meta{option}} and \index{where option=\meta{option}} keys.
-\index{if option=\meta{option}}|=|\meta{value}\meta{true options}\meta{false options} checks whether
-the value of \meta{option} equals \meta{value}. If so, \meta{true options} are
-processed, otherwise \meta{false options}. The \index{where option=\meta{option}} keys are
-the same, but do this for the every node in the subtree; informally
-speaking, |where| = |for_tree| + |if|. To see this in action,
-consider the rewrite of the \index{tier} example (\ref{ex:tier-manual}) from above. We don't set
-the tiers manually, but rather put the terminal nodes (option
-\index{n children} is a read-only option containing the number
-of children) on tier \keyname{word}.\footnote{We could omit the braces around \texttt{0} because
-it is a single character. If we were hunting for nodes with 42 children, we'd have to write
-\texttt{where n children=\{42\}...}.}
+We are now ready to learn about simple conditionals.\footnote{See \S\ref{ref:conditionals} for
+ further information on conditionals, including the generic \index{if} and \index{where}.} Every
+node option has the corresponding \index{if option=\meta{option}} and \index{where
+ option=\meta{option}} keys. \index{if option=\meta{option}}|=|\meta{value}\meta{true
+ options}\meta{false options} checks whether the value of \meta{option} equals \meta{value}. If
+so, \meta{true options} are processed, otherwise \meta{false options}. The \index{where
+ option=\meta{option}} keys are the same, but do this for the every node in the subtree; informally
+speaking, |where| = |for_tree| + |if|. To see this in action, consider the rewrite of the
+\index{tier} example (\ref{ex:tier-manual}) from above. We don't set the tiers manually, but rather
+put the terminal nodes (option \index{n children} is a read-only option containing the number of
+children) on tier \keyname{word}.\footnote{We could omit the braces around \texttt{0} because it is
+ a single character. If we were hunting for nodes with 42 children, we'd have to write
+ \texttt{where n children=\{42\}...}.}
\begin{forestexample}[index={tier,where option,n children}]
\begin{forest}
~where n children~=0{tier=word}{}
@@ -714,15 +743,26 @@
\end{forest}
\end{forestexample}
-Note that you usually don't want to embed a \index{where} conditional in a \index{for step=\index{tree}}, as this will lead to a multiple traversal of many nodes, resulting in a slower execution.
-If you're inside a \index{for step=\index{tree}}, you probably want to use \index{if}.
+\begin{advise}
+\item Note that you usually don't want to embed a \index{where option=...} conditional in a \index{for
+ step=\index{tree}}, as this will lead to a multiple traversal of many nodes, resulting in a
+ slower execution. If you're inside a \index{for step=\index{tree}}, you probably want to use
+ \index{if}.
+\end{advise}
-Finally, let's talk about styles. Styles are simply collections of
-options and/or other keys. (They are not actually defined in the \foRest; package, but
-rather inherited from |pgfkeys|.) If you often want to have non-default
-parent/child anchors, say south/north as in example (\ref{ex:tier-manual}), you would save some
-typing by defining a style. Styles are defined using \PGF;'s handler
-|.style|, like shown below.\footnote{Style \index{sn edges} is actually already defined by library \reflibrary{linguistics}. The definition there is a bit more generic.}
+
+Finally, let's talk about styles.
+(They are not actually defined in the \foRest; package, but rather
+inherited from |pgfkeys|.)
+
+
+
+
+At the first approximation, styles are abbreviations: if you
+often want to have non-default parent/child anchors, say south/north as in example
+(\ref{ex:tier-manual}), you could save some typing by defining a style. Styles are defined using
+\PGF;'s handler |.style|, like shown below.\footnote{Style \index{sn edges} is actually already
+ defined by library \reflibrary{linguistics}. The definition there is a bit more generic.}
\begin{forestexample}[index={tier,option>parent anchor,option>child anchor}]
\begin{forest}
~sn edges~/~.style~={for tree={
@@ -746,7 +786,7 @@
}
\end{lstlisting}
-You might have noticed that in the last two examples contain, some keys occurred even before the
+You might have noticed that in the last two examples, some keys occurred even before the
first opening bracket, contradicting was said at the beginning of this section. This is mainly
just syntactic sugar (it can separate the design and the content): such \emph{preamble}
keys behave as if they were given in the root node, the only difference (which often does not
@@ -754,7 +794,7 @@
\index{content}.
If you find yourself writing the same preamble for every tree in your document,
-consider redefining style \index{default preamble}, which is implicitely included at the beginning
+consider modifying \index{default preamble}, which is implicitely included at the beginning
of every preamble.
\subsection{Decorating the tree}
@@ -834,10 +874,10 @@
Finally, the most powerful tool in the node reference toolbox:
\emph{relative nodes}. It is possible to refer to other nodes which stand
in some (most often geometrical) relation to the current node. To
-do this, follow the node's name with a \index>{!} and a \emph{node walk}
+do this, follow the node's name with a \index>{!} and a \emph{nodewalk}
specification.
-A node walk is a concise\footnote{Actually, \foRest; distinguishes two kinds of steps in node walks:
+A nodewalk is a concise\footnote{Actually, \foRest; distinguishes two kinds of steps in node walks:
long-form and short-form steps. This section introduces only short-form steps. See
\S\ref{ref:nodewalks}.} way of expressing node relations. It is simply a string of steps, which
are represented by single characters, where: \index{ss u} stands for the parent node (up); \index{ss
@@ -884,7 +924,7 @@
\end{forestexample}%
\endgroup
-The second example uses \TikZ;'s fitting library to compute the
+The second example uses \TikZ;'s fitting library (automatically loaded by \foRest;) to compute the
smallest rectangle containing node VP, its first child (DP$_2$) and its last grandchild (DP$_3$).
The example also illustrates that the \TikZ; code
can be specified via the ``normal'' option syntax, i.e.\ as a value
@@ -915,19 +955,23 @@
controlled by option \index{grow}=\meta{direction}.\footnote{The direction can be specified either in
degrees (following the standard mathematical convention that $0$ degrees is to the right, and that
degrees increase counter-clockwise) or by the compass directions: \texttt{east}, \texttt{north east},
- \texttt{north}, etc.} The system thus computes and stores the positions of children using a
+ \texttt{north}, etc.} The system computes and stores the positions of children using a
coordinate system dependent on the parent, called an \emph{ls-coordinate system}: the origin is the
parent's anchor; l-axis is in the direction of growth in the parent; s-axis is orthogonal to the
l-axis (positive side in the counter-clockwise direction from $l$-axis); l stands for \emph{l}evel,
-s for \emph{s}ibling. The example shows the ls-coordinate system for a node with |grow=45|.
+s for \emph{s}ibling. The example shows the ls-coordinate system for a node with
+|grow=45|.\footnote{The axes are drawn using coordinates given in \texttt{forest cs} coordinate
+ system; the ``manually'' given polar coordinate equivalent is shown in the comment.}
-\begin{forestexample}[point=grow,index=grow]
+\begin{forestexample}[point=grow,index={grow}]
\begin{forest} background tree
[parent, grow=45
[child 1][child 2][child 3][child 4][child 5]
]
- \draw[,->](-135:1cm)--(45:3cm) node[below]{$l$};
- \draw[,->](-45:1cm)--(135:3cm) node[right]{$s$};
+ %\draw[,->](-135:1cm)--(45:3cm) node[below]{$l$};
+ \draw[,->](forest cs:l=-1cm,s=0)--(forest cs:l=3cm,s=0) node[below]{$l$};
+ %\draw[,->](-45:1cm)--(135:3cm) node[right]{$s$};
+ \draw[,->](forest cs:s=-1cm,l=0)--(forest cs:s=3cm,l=0) node[right]{$s$};
\end{forest}
\end{forestexample}
@@ -956,18 +1000,19 @@
\input{\jobname.tmp}
-The l-coordinate of children is (almost) completely under your control, i.e.\ you set what is
-often called the level distance by yourself. Simply set option \index{option>l} to change the
-distance of a node from its parent. More precisely, \index{option>l}, and the related option
+The l-coordinate of children is (almost) completely under your control, i.e.\ you set what is often
+called the level distance by yourself. Simply set option \index{option>l} to change the distance of
+a node from its parent.\footnote{If setting \index{option>l} seems to have no effect, read about
+ \index{l sep} further down this section.} More precisely, \index{option>l}, and the related option
\index{option>s}, control the distance between the (node) anchors of a node and its parent. The
-anchor of a node can be changed using option \index{option>anchor}: by default, nodes are anchored at
-their base; see \cite[\S16.5.1]{tikzpgf2.10}.) In the example below, positions of the anchors are
-shown by dots: observe that anchors of nodes with the same \index{option>l} are aligned and that the
-distances between the anchors of the children and the parent are as specified in the
+anchor of a node can be changed using option \index{option>anchor}: by default, nodes are anchored
+at their base; see \cite[\S16.5.1]{tikzpgf2.10}.) In the example below, positions of the anchors
+are shown by dots: observe that anchors of nodes with the same \index{option>l} are aligned and that
+the distances between the anchors of the children and the parent are as specified in the
code.\footnote{Here are the definitons of the macros for measuring distances. Args: the x or y
-distance between points \#2 and \#3 is measured; \#4 is where the distance line starts (given as an
-absolute coordinate or an offset to \#2); \#5 are node options; the optional arg \#1 is the format of
-label. (Lengths are printed using package \texttt{printlen}.)
+ distance between points \#2 and \#3 is measured; \#4 is where the distance line starts (given as
+ an absolute coordinate or an offset to \#2); \#5 are node options; the optional arg \#1 is the
+ format of label. (Lengths are printed using package \texttt{printlen}.)
\box\codebox}
\begin{forestexample}[layout=tree on top,index={for step,tree,tikz,option>l,option>anchor},index>={!}]
@@ -1139,8 +1184,8 @@
situation using a bottom-aligned multiline node. (Multiline nodes can be easily created using |\\|
as a line-separator. However, you must first specify the horizontal alignment using option
\index{align} (see \S\ref{ref:node-appearance}).
-Bottom vertical alignment is achieved by setting \index{base}|=|\index{value=base>bottom};
-the default, unlike in \TikZ;, is \index{base}|=|\index{value=base>top}).
+Bottom vertical alignment is achieved by setting \index{base}|=|\index{value of=base>bottom};
+the default, unlike in \TikZ;, is \index{base}|=|\index{value of=base>top}).
\begin{forestexample}[point={align,base},index={align,base}]
\begin{forest}
[parent
@@ -1159,7 +1204,7 @@
you used lots of parenthesis in your nodes? And got a strange vertical misalignment, like below
on the right? Then rest assured that these (at least) are features not bugs and read
\S\ref{tut:defaults}.
-\begin{forestexample}[layout=tree on top,v sep=-55ex,code left skip=-3cm,label=ex:misalignments,index={option>phantom,for step,step>children,fit,propagator>for,baseline,edge,descendants,content,pgfmath,ss 1}]
+\begin{forestexample}[layout=tree on top,v sep=-55ex,code left skip=-3cm,label=ex:misalignments,index={option>phantom,for step,step>children,fit,baseline,edge,descendants,content,pgfmath,ss 1}]
\begin{forest}
[,phantom,for children={l sep=1ex,fit=band,
for 1={edge'=,l=0},baseline}
@@ -1274,18 +1319,18 @@
is true for the reverse possibility, setting a default \index{option>l} (and leaving \index{l sep} at 0). In the example below, the depth of the multiline node (anchored at the top
line) is such that the child--parent edges are just too short if the level distance is kept constant.
Sometimes, misalignment is much preferred \dots
-\begin{forestexample}[index={align,{value=align>center},for step,tree,l sep}]
+\begin{forestexample}[index={align,{value of=align>center},for step,tree,l sep}]
\mbox{}\begin{forest}
- [default
+ [default,baseline
[first child[a][b][c]]
- [second child\\[-1ex]\scriptsize(a copy),
+ [{second child\\[-1ex]\scriptsize(a copy)},
align=center[a][b][c]]
]
- \end{forest}\\
+ \end{forest}\quad
\begin{forest} for tree={l sep=0}
- [{\texttt{l sep}=0}
+ [{\texttt{l sep}=0},baseline
[first child[a][b][c]]
- [second child\\[-1ex]\scriptsize(a copy),
+ [{second child\\[-1ex]\scriptsize(a copy)},
align=center[a][b][c]]
]
\end{forest}
@@ -1308,19 +1353,20 @@
indices, the default works.
The standard node can be changed using macro \index{forestStandardNode};
-see \ref{ref:standard-node}.
+see \ref{ref:standard-node}.
+% TODO: primer? ali raje po spremembi interfaceja
\subsection{Advanced option setting}
\label{tut:advanced-option-setting}
-We have already seen that the value of options can be manipulated: in (\ref{ex:romannumeral}) we have
-converted numeric content from arabic into roman numerals using the \emph{wrapping} mechanism
-|content=\romannumeral#1|; in (\ref{ex:l*}), we have tripled the value of |l|
-by saying |l*=3|. In this section, we will learn about the mechanisms for setting and
-referring to option values offered by \foRest;.
+We have already seen that the value of options can be manipulated: in (\ref{ex:romannumeral}), we
+have converted numeric content from arabic into roman numerals using the \emph{wrapping} mechanism
+|content=\romannumeral#1|; in (\ref{ex:l*}), we have tripled the value of |l| by saying |l*=3|. In
+this section, we will learn more about the mechanisms for setting options and referring to their
+values.
One other way to access an option value is using macro \index{forestoption}. The macro takes a
-single argument: an option name. (For details, see \S\ref{sec:option-reading}.) In the
+single argument: an option name. In the
following example, the node's child sequence number is appended to the existing content. (This is
therefore also an example of wrapping.)
\begin{forestexample}[label=ex:forestoption,index={option>phantom,delay,for step,descendants,content,readonly option>n,forestoption}]
@@ -1331,11 +1377,11 @@
\end{forest}
\end{forestexample}
-However, only options of the current node can be accessed using \index{forestoption}. To
-access option values of other nodes, \foRest;'s extensions to the \PGF;'s mathematical library
-|pgfmath|, documented in \citep[part VI]{tikzpgf2.10}, must be used. To see |pgfmath| in action,
+However, only options of the current node can be accessed using \index{forestoption}. Possibly the simplest way to
+access option values of other nodes is to use \foRest;'s extensions to the \PGF;'s mathematical library
+|pgfmath|, documented in \citep[part VI]{tikzpgf2.10}. To see |pgfmath| in action,
first take a look at the crazy tree on the title page, and observe how the nodes are
-rotated: the value given to (\TikZ;) option \texttt{rotate} is a full-fledged |pgfmath| expression
+rotated: the value given to option \index{rotate} is a full-fledged |pgfmath| expression
yielding an integer
in the range from $-30$ to $30$. Similiarly, \index{dimen+=l} adds a random float
in the $[-5,5]$ range to the current value of \index{option>l}.
@@ -1370,7 +1416,7 @@
current node is just a short-hand notation for \texttt{option\string_name()} --- note that in some
contexts, like preceding \texttt{+} or \texttt{-}, the short form does not work! (The same
seems to be true for all pgfmath functions with ``optional'' arguments.)} In the next example, we
-rotate the node based on the content of its parent.
+rotate the node based on the content of its parent (\index{short step>u} means `up').
\begin{forestexample}[index={delay,for step,descendants,content,ss u},index>={!}]
\begin{forest}
delay={for descendants={rotate=content~("!u")~}}
@@ -1380,15 +1426,92 @@
Note that the argument of the option function is surrounded by double quotation marks: this is
to prevent evaluation of the relative node name as a |pgfmath| function --- which it is not.
-Handlers \index{wrap pgfmath arg} and \index{wrap $n$ pgfmath args}
-(for $n=2,\dots,8$) combine the wrapping mechanism with the |pgfmath| evaluation. The
-idea is to compute (most often, just access option values) arguments using |pgfmath| and then
-wrap them with the given macro. Below, this is used to include the number of parent's children in
-the index.
-\begin{forestexample}[index={option>phantom,delay,for step,descendants,content,readonly option>n,n children,wrap $n$ pgfmath args},index>={!}]
+For further ways to access option values, see \S\ref{tut:wrapping}. Here, we continue by introducing
+\emph{relative node setting}: write \index{relative node name}|.|\meta{option}|=|\meta{value} to set
+the value of \meta{option} of the specified relative node. Important: computation of the value is
+done in the context of the original node. The following example defines style \keyname{move} which
+not only draws an arrow from the source (the current node) to the target, but also moves the content
+of the source to the target (leaving a trace). Note the difference between |#1| and |##1|: |#1| is
+the argument of the style \keyname{move} (a node walk determining the target), while |##1| is the
+original option (in this case, \indexex{option>content}) value.
+\begin{forestexample}[index={for step,tree,calign,tikz,delay,content},index>={!}]
+ \begin{forest}
+ for tree={calign=fixed edge angles},
+ move/.style={
+ tikz={\draw[->] () to[out=south west,in=south] (#1);},
+ delay={~#1.content~={##1},content=$t$}},
+ [CP[][C'[C][\dots[,phantom][VP[DP][V'[V][DP,move=!r1]]]]]]
+ \end{forest}
+\end{forestexample}
+
+\begin{forestexample}[index={if option,n children,content,for step,step>children,delay,pgfmath},index>={!},basicstyle=\scriptsize\ttfamily,layout=export]
+ \begin{forest}
+ calc/.style={if n children={0}{}{content=0,for children={calc,~!u.content~/.pgfmath=int(content("!u")+content())}}},
+ delay=calc,
+ [[[3][4][5]][[3][9]][8][[[1][2][3]]]]
+ \end{forest}
+\end{forestexample}
+
+In the following example, the content of the branching nodes is computed by \foRest;: a branching
+node is a sum of its children. The algorithm visits each node (but the root node) and adds its
+content to the content of the parent. Note that as the computation must proceed bottom-up,
+\index{for step=\index{descendants children-first}} propagator is used to walk through the
+tree.\footnote{It would be possible to emulate \index{for step=\index{descendants children-first}}
+ by defining a recursive style, as was done in this manual for versions of the package prior to
+ introduction of the bottom-up propagator. The following code produces identical result as the code
+ in the main text.
+
+ \box\codebox}
+
+\begin{forestexample}[index={if option,n children,content,for step,step>children,delay,pgfmath},index>={!}]
+ \begin{forest}
+ delay={
+ where n children={0}{}{content=0},
+ for descendants children-first={
+ ~!u.content~/.pgfmath=int(content("!u")+content())}
+ }
+ [[[3][4][5]][[3][9]][8][[[1][2][3]]]]
+ \end{forest}
+\end{forestexample}
+
+Actually, for common computations such as summing things up, \foRest; provides an easier way to do it: aggregate functions (\S\ref{ref:aggregate-functions}). Below, aggregate function \index{sum}, defined as |pgfkeys| handler, walks through the \index{step>children} (second argument) of the current node, summing up their \index{content} (first argument) and stores the result as the \index{content} of the current node (because \index{content} is the handled key).
+
+\begin{forestexample}[index={sum,aggregate postparse,for step,tree children-first,delay,n children,if option,content,step>children}]
+ \begin{forest}
+ delay={
+ aggregate postparse=int,
+ for tree children-first={
+ if n children={0}{}{
+ content/~.sum~={content}{children}
+ }
+ }
+ }
+ [[[3][4][5]][[3][9]][8][[[1][2][3]]]]
+ \end{forest}
+\end{forestexample}
+
+\subsection{Wrapping}
+\label{tut:wrapping}
+
+We have already seen examples of inserting option values into other expressions. In example
+(\ref{ex:romannumeral}), we have wrapped the value of the option being assigned to (|#1| stood for
+the current value of option \index{content}); example (\ref{ex:forestoption}) additionally wrapped
+the value of option \index{readonly option>n} (of the current node) using macro \index{forestoption}. In general,
+\foRest; offers two ways to perform computations (from simple option value lookups to
+complicated formulas) and insert their results into another expression (of any kind: \TeX\ code,
+|pgfkeys| keylist, |pgfmath| expression, etc.).
+
+Historically, the first \foRest;'s mechanism that offered wrapping of computed values were handlers
+\index{wrap pgfmath arg} and \index{wrap $n$ pgfmath args} (for $n=2,\dots,8$), which combine the
+wrapping mechanism with the |pgfmath| evaluation. The idea is to compute (most often, just access
+option values) arguments using |pgfmath| and then wrap them into the given macro body (marked below)
+using \TeX's parameters (|#1| etc.). Below, this is used to subscript the contents of a node with
+its sequential number and the number of parent's children.
+\begin{forestexample}[index={option>phantom,delay,for step,descendants,content,readonly option>n,n children,wrap $n$ pgfmath args},index>={!},label=ex:pgfmathwrap]
\begin{forest} [,phantom,delay={for descendants={
- ~content/.wrap 3 pgfmath args=
- {#1$_{#2/#3}$}{content}{n}{n_children("!u")}~}}
+ content/.wrap 3 pgfmath args=
+ ~{#1$_{#2/#3}$}~
+ {content}{n}{n_children("!u")}}}
[c][o][u][n][t]]
\end{forest}
\end{forestexample}
@@ -1398,15 +1521,15 @@
As another example, let's make the numerals example (\ref{ex:numerals-simple}) a bit fancier.
The numeral type is read off the parent's content and used to construct the appropriate control
-sequence (|\@arabic|, |\@roman| and |\@alph|). (Also, the numbers are not specified in content
-anymore: we simply read the sequence number \index{readonly option>n}. And, to save some horizontal space for the
-code, each child of the root is pushed further down.)
+sequence (|\@arabic|, |\@roman| and |\@alph|). (The numbers are not specified in content
+anymore: we simply read the sequence number \index{readonly option>n}.)
\begin{forestexample}[index={delay,where option,readonly option>level,content,readonly option>n,for step,step>children,option>l,wrap $n$ pgfmath args},index>={!}]
\begin{forest}
- delay={where level={2}{~content/.wrap 2 pgfmath args=
- {\csname @#1\endcsname{#2}}{content("!u")}{n}~}{}},
+ delay={where level={2}{content/.wrap 2 pgfmath args=
+ {\csname @#1\endcsname{#2}}
+ {content("!u")}{n}}{}},
for children={l*=n},
- [\LaTeX numerals,
+ [\LaTeX\ numerals,
[arabic[][][][]]
[roman[][][][]]
[alph[][][][]]
@@ -1414,73 +1537,121 @@
\end{forest}
\end{forestexample}
-The final way to use |pgfmath| expressions in \foRest;: |if| clauses. In
-section~\ref{tut:options}, we have seen that every option has a corresponding \index{if option=\meta{option}}
-(and \index{where option=\meta{option}} key. However, these are just a matter of convenience. The full
-power resides
-in the general \index{conditional>if} conditional, which takes three arguments:
-|if=|\meta{condition}\meta{true options}\meta{false options}, where \meta{condition} can be any
-|pgfmath| expression
-(non-zero means true, zero means false). (Once again, propagator \index{propagator>where} is an abbreviation
-for \index{for step=\index{tree}}|={|\index{conditional>if}|=...}|.) In the following example, \index{conditional>if} option
-is used to orient the
-arrows from the smaller number to the greater, and to color the odd and even numbers differently.
+Invoking |pgfmath| is fairly time consuming and using it to do nothing but retrieve an option value
+seems a bit of an overkill. To remedy the situation, argument processor
+(\S\ref{ref:argument-processor}) was introduced in \FoRest; v2.0 and considerably expanded in v2.1.
+One way to invoke it is using handler \index{handler>process}.
-\forestset{random tree/.style n args={3}{% #1=max levels, #2=max children, #3=max content
- content/.pgfmath={random(0,#3)},
- if={#1>0}{repeat={random(0,#2)}{append={[,random tree={#1-1}{#2}{#3}]}}}{}}}
-\begin{forestexample}[index={before typesetting nodes,for step,descendants,conditional>if,content,edge,edge label,tree},index>={!},point=if]
- \pgfmathsetseed{314159}
+The argument processor takes a sequence of instructions and an arbitrary number of arguments,
+transforms the given arguments according to the instructions, and feeds the resulting list of
+arguments into the handled key.
+
+An instruction is given by a single-character code. The simplest instructions are:
+\index{processor>O}, which expects its argument to be an option name (possibly preceded by a
+\index{relative node name}|.| to access the option value of a non-current node) and returns the
+value of the option; \index{processor>R}, which does the same for registers; and \index{processor>noop}, which
+leaves the argument unchanged.
+
+In the following example, we define style |test| taking four arguments and call it by providing
+the arguments via \index{handler>process}. The instruction string |ROO__| tells the argument processor that
+the first argument is the value of (scratch) register \indexex{temptoksa}, the second the value of
+option \indexex{n children} at the current node, the third the value of option \indexex{content} of
+the second child of the current node, and the fourth just a plain string. Macro |test| is thus
+actually invoked with argument list |{Hello}{3}{Jane}{Goodbye}|.
+
+\begin{forestexample}[index={handler>process,processor>noop,processor>R,processor>O,delay,content,n
+children,temptoksa}]
\begin{forest}
- before typesetting nodes={
- for descendants={
- if={content()>content("!u")}{edge=->}{
- if={content()<content("!u")}{edge=<-}{}},
- edge label/.wrap pgfmath arg=
- {node[midway,above,sloped,font=\scriptsize]{+#1}}
- {int(abs(content()-content("!u")))}
- },
- for tree={circle,if={mod(content(),2)==0}
- {fill=yellow}{fill=green}}
- }
- [,random tree={3}{3}{100}]
+ test/.style n args={4}{align=center,
+ content={#1!\\I have #2 children.\\One of them is #3.\\#4!}}
+ [,delay={temptoksa=Hello,
+ test/.process={~ROO_~}{temptoksa}{n children}{!2.content}{Goodbye}}
+ [John][Jane][Joe]]
\end{forest}
\end{forestexample}
-This exhausts the ways of using |pgfmath| in forest. We continue by introducing \emph{relative
-node setting}: write \index{relative node name}|.|\meta{option}|=|\meta{value} to set the
-value of \meta{option} of the specified relative node. Important: computation (pgfmath or wrap) of
-the value is
-done in the context of the original node. The following example defines style \keyname{move} which
-not only draws an arrow from the source to the target, but also moves the content of the source
-to the target (leaving a trace). Note the difference between |#1| and |##1|: |#1| is the argument
-of the style \keyname{move}, i.e.\ the given node walk, while |##1| is the original option value
-(in this case, content).
-\begin{forestexample}[index={for step,tree,calign,tikz,delay,content},index>={!}]
+To wrap using the argument processor, use instruction \index{processor>w}. Unless wrapping a single
+argument, this instruction should be followed by a number indicating the number of arguments
+consumed. \index{processor>w} will take the required number of arguments from the list of already
+processed arguments and wrap them in the macro body given as the next (yet unprocessed) argument.
+
+The following example has the same result as example (\ref{ex:pgfmathwrap}). Note that the
+order of the wrapper-macro body and the arguments is different for \index{handler>process} and \index{wrap
+ $n$ pgfmath args}. (Experience shows that \index{handler>process}'s order is easier on the eyes.) The
+example also illustrates that (i) the instructions need not be enclosed in braces and (ii) that
+repetition of an argument processor instruction can be indicated by appending a number to the
+instruction: thus |O3| below means the same as |OOO|.
+
+\begin{forestexample}[index={option>phantom,delay,for step,descendants,content,readonly option>n,n children},index>={!}]
+ \begin{forest} [,phantom,delay={for descendants={
+ content/.process=~O3 w3~
+ {content}{n}{!u.n children}
+ {#1$_{#2/#3}$}
+ }}
+ [c][o][u][n][t]]
+ \end{forest}
+\end{forestexample}
+
+Note that the order of the wrapper-macro body and the arguments is different for
+\index{handler>process} and \index{wrap $n$ pgfmath args}. Experience shows that
+\index{handler>process}'s order is easier on the eyes. The example also illustrates that the
+instructions need not be enclosed in braces and that repetition of an argument processor instruction
+can be indicated by appending a number to the instruction: |O3| above is equivalent to |OOO|.
+
+% \begin{forestexample}[index={process,processor>w}]
+% \begin{forest}
+% [root,delay={align=center,
+% content/.process={OO ~w2~}
+% {n children}{content}
+% {This node has #1 children.\\It's original content is ``#2''.}
+% }]
+% \end{forest}
+% \end{forestexample}
+
+\index{wrap $n$ pgfmath args} always returns a single braced expression and is thus a bit cumbersome
+to use when the handled key expects multiple arguments: the trick is to enclose the expected
+argument list in extra braces (marked in the code below). As \index{handler>process} can return multiple
+arguments, there is no need for such a workaround. See the following example for comparison of the
+two methods.
+
+\begin{forestexample}[index={for step,step>name,handler>process,processor>O,processor>w,wrap $n$ pgfmath args}]
\begin{forest}
- for tree={calign=fixed edge angles},
- move/.style={
- tikz={\draw[->] () to[out=south west,in=south] (#1);},
- delay={~#1.content~={##1},content=$t$}},
- [CP[][C'[C][\dots[,phantom][VP[DP][V'[V][DP,move=!r1]]]]]]
+ [,phantom
+ [pgfmath[2,delay={for n/.wrap 2 pgfmath args=
+ ~{~{#1}{content=#2,draw}~}~
+ {content}{content("!u")}
+ } [x][x][x][x]]]
+ [process[3, delay={for n/.process=
+ {O Ow1}{content}
+ {!u.content}{content=#1,draw}
+ } [x][x][x][x]]]
+ ]
\end{forest}
\end{forestexample}
-In the following example, the content of the branching nodes is computed by \foRest;: a branching
-node is a sum of its
-children. Besides the use of the relative node setting, this example notably uses a recursive
-style: for each child of the node, style \keyname{calc} first applies itself to the child and then
-adds the result to the node; obviously, recursion is made to stop at terminal nodes.
-\begin{forestexample}[index={if option,n children,content,for step,step>children,delay,pgfmath},index>={!}]
+A single \index{handler>process} invocation can perform multiple wrappings. The numbering of arguments of
+each wrapping starts at |#1|. In the example below, \index{for step=\index{nodewalk}} takes two
+arguments, a nodewalk and a list of nodekeys. Each is produced by an independent wrapping (wrap bodies
+are marked in the code).
+
+\begin{forestexample}[index={handler>process,processor>R,processor>w,for step,nodewalk,+toks,content}]
\begin{forest}
- calc/.style={if n children={0}{}{content=0,for children={
- calc,~!u.content~/.pgfmath=int(content("!u")+content())}}},
- delay=calc,
- [[[3][4][5]][[3][9]][8][[[1][2][3]]]]
+ declare toks register=prefix,
+ declare count register=level to prefix,
+ prefix=X-,
+ level to prefix=1,
+ delay={
+ for nodewalk/.process=Rw Rw
+ {level to prefix}{~level=#1~}
+ {prefix}{~+content=#1~}
+ }
+ [0[1[2]][3[4][5]][6[7][8][9]]]
\end{forest}
\end{forestexample}
+
+
\subsection{Externalization}
\label{tut:externalization}
@@ -1541,7 +1712,7 @@
The action character is not hard coded into \foRest;. Actually, there is no action character by
default. (There's enough special characters in \foRest; already, anyway, and the situations where
-controlling the expansion is preferable to using the pgfkeys interface are not numerous.) It is
+controlling the expansion is preferable to using the |pgfkeys| interface are not numerous.) It is
defined at the top of the example by processing key \index{action character} in the
|/bracket| path; the definition is local to the \TeX\ group.
@@ -1608,7 +1779,7 @@
\label{sec:reference}
This section documents all publicly exposed keys and macros defined by the core package. All other
-commands defined by the package (see the implementation typeset in |forest.doc|) are considered
+commands defined by the package (see the implementation typeset in |forest.pdf|) are considered
internal and might change without prior notice or compatibility support.
\subsection{Package loading and options}
@@ -1672,23 +1843,26 @@
step=\meta{step}}, where a propagator could not fail.
While each compatibility feature can be enabled individually, they are grouped for ease of use. To
-load compatibility features since version |x|[|.y|[|.z|]], write |compat=x|[|.y|[|.z|]]|-all| or
+load compatibility features since the last version of form
+|x|[|.y|[|.z|]], write |compat=x|[|.y|[|.z|]]|-all| or
|compat=x|[|.y|[|.z|]]|-most|. The former enables all compatibility features since that release, the
latter only those that are guaranteed to not disrupt any new functionality of the package.
To load all compatibility features since the last major release (|x| in |x.y.z|), write
-|compat=|\indexdef{option of=compat>all}; to load most of them, write |compat=|\indexdef{option
- of=compat>most} or simply |compat|.
+|compat=|\indexdef{value of=compat>all}; to load most of them, write |compat=|\indexdef{value of=compat>most} or simply |compat|.
+To enable multiple compatibility features, either use this option multiple times, or provide it with
+a comma-separated list of compatibility features. (Surround the list by braces.)
+
Specifying this option also defines macro \indexdef{macro>forestcompat} (taking the same arguments
as the package option) which can be used to enable compatibility features locally, within the
document body. To enable compatibility mode but not enable any specific compatibility feature for
-the entire document, write |compat=|\indexdef{option of=compat>none} as a package option.
+the entire document, write |compat=|\indexdef{value of=compat>none} as a package option.
For a list of compatibility features, see \S\ref{sec:changelog}.
By default, the package warns when a compatibility feature is used. Disable this behaviour by
-|compat=|\indexdef{option of=compat>silent}.
+|compat=|\indexdef{value of=compat>silent}.
\indexitem(true){package option>tikzcshack}|=|\alternative{true,false}
@@ -1705,8 +1879,9 @@
available information, otherwise only the information on the listed (comma-separated) debug categories. The available categories are listed below.
\begin{syntax}
- \indexitem{option of=debug>nodewalks}
- \indexitem{option of=debug>dynamics}
+ \indexitem{value of=debug>nodewalks}
+ \indexitem{value of=debug>dynamics}
+ \indexitem{value of=debug>process}
\end{syntax}
\end{syntax}
@@ -1744,11 +1919,14 @@
}
\end{forestexample}}
- Using \meta{config}, it is possible to configure behaviour of the environment/macro prior to
- application of \index{style>stages}. The following keys are defined.
+\meta{config} is a keylist that configures the behaviour of the environment/macro. The
+configuration is the first operation that the environment/macro does; it precedes even the reading
+of the tree specification. Currently, \meta{config} accepts only one key:
\begin{syntax}
- \indexitem{option of=forest>stages}|=|\meta{style definition} overrides the contents of style
- \index{style>stages} for the current environment/macro.
+ \indexitem{option of=forest>stages}|=|\meta{keylist}
+
+ By default, after reading the tree specification, \foRest; executes style \index{style>stages}.
+ If key |stages| is used in \meta{config}, \meta{keylist} is executed instead.
\end{syntax}
\indexitem{macro>forestset}\marg{keylist}
@@ -1838,7 +2016,7 @@
computed so that the nodes don't overlap. That's difficult. The result: option \index{option>s} is
set for all nodes. (Sometimes, the value of \index{option>l} is adjusted as well.)
\item\label{step:compute-xy} Absolute positions, or rather, positions of the nodes relative to the
- root node are computed. That's easy. The result: options \index{x} and \index{y} are
+ root node are computed. That's easy. The result: options \index{option>x} and \index{y} are
set.
\item\label{step:draw-tree} The \TikZ; code that will draw the tree is produced and executed. (The nodes are
drawn by using the boxes typeset in step~\ref{step:typeset-nodes}.)
@@ -1858,7 +2036,7 @@
Second, the execution of the processing stages \ref{step:given-options}--\ref{step:draw-tree} is
\emph{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 \keyname{stages},
+is twofold. The outer level: \foRest; initiates the processing by executing style \index{style>stages},
which by default executes the processing stages \ref{step:given-options}--\ref{step:draw-tree},
preceding the execution of each but the first stage by processing the keys embedded in temporal
propagators \keyname{before ...} (see \S\ref{ref:temporal-propagators}). The inner level: each
@@ -1930,13 +2108,13 @@
(Experimental, use with care, especially when combining with tier alignment.)
\indexitem{stage>compute xy} Computes the positions of the nodes in the subtree relative to the
- current node. The results are stored into options \index{x} and \index{y}. The current node's
- \index{x} and \index{y} remain unchanged.
+ current node. The results are stored into options \index{option>x} and \index{y}. The current node's
+ \index{option>x} and \index{y} remain unchanged.
\indexitem{stage>draw tree}
\itemnosep
\indexitem{stage>draw tree'}
- Produces and executed the \TikZ; code that draws the (sub)tree rooted in the current node.
+ Produces and executes the \TikZ; code that draws the (sub)tree rooted in the current node.
The procedure uses the node boxes typeset by \index{typeset nodes} or friends. The |'| variant
includes the node boxes in the picture using \cmdname{copy}, not \cmdname{box}, thereby preserving
@@ -1968,7 +2146,8 @@
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 \index{style>stages}.
The calls of this key should \emph{not} be nested, and it should not be embedded under
\index{process keylist'} or \index{process keylist register}.
@@ -2027,22 +2206,23 @@
This key is safe to use within \index{process keylist}, \index{process keylist'} and
\index{process keylist register}.
-\indexitem(tree){nodewalk style>processing order}|=|\meta{nodewalk}
+\indexitem(tree){nodewalk style>processing order}|/.nodewalk style=|\meta{nodewalk}
Redefine this style to change the default order in which \index{process keylist} processes a keylist
option. For example, to process the nodes in a child-first fashion, write
\begin{lstlisting}
- for nodewalk={processing order/.style={tree children first}}{}
+ processing order/.nodewalk style=tree children first
\end{lstlisting}
-Note that this is a \emph{nodewalk} style, so it must be defined during a nodewalk.
+Note that this is a \emph{nodewalk} style, so it must be defined either using |.style| handler
+during a nodewalk or using \index{nodewalk style}.
-\indexitem(processing order)[form={processing order}]{word suffix=keylist option>nodewalk style>processing order=\meta{keylist option}}|=|\meta{nodewalk}
+\indexitem(processing order)[form={processing order}]{word suffix=keylist option>nodewalk style>processing order=\meta{keylist option}}|/.nodewalk style=|\meta{nodewalk}
Redefine this style to change the \index{process keylist} processing order for a specific
\meta{keylist option}. For example, to process \index{before drawing tree} options in the
child-first fashion, leaving the processing of other |before ...| keylists untouched, write
\begin{lstlisting}
- for nodewalk={before drawing tree processing order/.style={tree children first}}{}
+ before drawing tree processing order/.nodewalk style=tree children first
\end{lstlisting}
\indexitem{node key>do dynamics} Experimental. Perform pending dynamic tree operations.
@@ -2055,12 +2235,12 @@
\label{ref: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 |before_...| and |after_...|
-propagators defer the processing of the given keys to a hook just before some stage in the workflow
-(\S\ref{ref:stages}). \index{before packing node} and \index{after packing node} are special as
-they fire \emph{during} the packing stage. The \keyname{delay} propagator is ``internal'' to the
-current hook: the keys in the hook are processed cyclically, and \keyname{delay} delays the
-processing of the given keys until the next cycle.
+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 (\S\ref{ref:stages}). \index{before packing node} and \index{after packing node} are
+special as they fire \emph{during} the packing stage. The \index{delay} propagator is
+``internal'' to the current hook: the keys in the hook are processed cyclically, and \keyname{delay}
+delays the processing of the given keys until the next cycle.
Formally, temporal propagators are keylist options (except \index{delay n}, which is a style), so
augmented assignments are possible (\S\ref{sec:option-setting}).
@@ -2136,7 +2316,7 @@
the processing of the \meta{keylist} given to the node to until just after \emph{this specific
node} is packed.
-\begin{forestexample}[index={after packing node,no edge,calign,value=calign>first,option>l,l sep,content format,content,if option,n children,pgfmath,option>s,max x,min x,for step,step>children,wrap pgfmath arg,typeset node,dimen+=s}]
+\begin{forestexample}[index={after packing node,no edge,calign,value of=calign>first,option>l,l sep,content format,content,if option,n children,pgfmath,option>s,max x,min x,for step,step>children,wrap pgfmath arg,typeset node,dimen+=s}]
\forestset{box/.style={
draw, no edge, l=0, l sep=1.5ex,
calign=first, anchor=base west,
@@ -2335,6 +2515,9 @@
\dots)
\end{advise}
+By default, unknown keys are assumed to be \TikZ; keys and are forwarded to \index{node options}.
+This behaviour can be changed using \index{unknown to}.
+
The following subsections list the node keys which are not described elsewhere (see above): spatial
propagators (\S\ref{ref:spatial-propagators}) and general-purpose node keys, i.e.\ those which don't
deal with tree formatting (\S\ref{sec:node-keys-various}).
@@ -2345,25 +2528,33 @@
Spatial propagators pass the given \meta{keylist} to other node(s) in the tree.
+Spatial propagation does not change the current node: after visiting the nodes the keys are
+propagated to, a spatial propagator (silently, using a so-called fake step) returns to the origin of
+the embedded nodewalk.
+
\FoRest; provides many spatial propagators. Almost all of them are built from long-form nodewalk
-steps using prefix \index{for step}. This is why the list below is so short: it only documents
-this prefix and the exceptions. For the list of nodewalk steps, see \S\ref{ref:nodewalks}.
+steps using prefix \index{for step}. This is why the list below is so short: it only documents this
+prefix and the exceptions. For the list of nodewalk steps, see \S\ref{ref:nodewalks}, in particular
+\S\ref{ref:single-step-keys} for single-step keys and \S\ref{ref:multi-step-keys} for multi-step
+keys.
-Spatial propagation does not change the current node: after visiting the nodes the keys are
-propagated to, a spatial propagator (silently) returns to the origin of the embedded nodewalk.
\begin{syntax}
-\indexitem{word prefix=step>propagator>for=\meta{step}}|=|\meta{arg$_1$}|...|\meta{arg$_n$}\meta{keylist}
+\indexitem{word prefix=step>propagator>for=\meta{step}}|=|\meta{arg$_1$}|...|\meta{arg$_n$}\meta{keylist: every-step}
+\itemnosep
+\indexitem[not short]{word prefix=step>propagator>for=\index{nodewalk}}|=|\meta{nodewalk}\meta{keylist: every-step}
+\itemnosep
+\indexitem[not short]{word prefix=step>propagator>for=\index{nodewalk key>Nodewalk}}|=|\meta{keylist: config}\meta{nodewalk}\meta{keylist: every-step}
Walks the (single- or multi-step) \meta{step} from the current node and executes the given
\meta{keylist} at every visited node. The current node remains unchanged.
- \meta{step} must be a long-form nodewalk step. If it has any arguments, they should be given
- before the keylist, with one exception: \meta{keylist: every-step} arguments of embedded nodewalks
- should be omitted, as it makes no sense to provide the every-step keylist twice.
+ \meta{step} must be a long-form nodewalk step. If it has any arguments, they
+ (\meta{arg$_1$}|...|\meta{arg$_n$}) should be given before every-step \meta{keylist}, with two
+ exceptions: embedded nodewalk steps (\index{step>Nodewalk} and \index{nodewalk}) already require
+ the \meta{keylist: every-step} argument, so it should be omitted, as it makes no sense to provide
+ the every-step keylist twice.
- For details on nodewalk steps, see \S\ref{ref:nodewalks}.
-
Examples:
\begin{itemize}
\item |for_parent={l_sep+=3mm}|
@@ -2372,6 +2563,40 @@
\item |for_tree={s_sep+=1em}|
\end{itemize}
+\long\def\printbigbadforlist#1{%
+ {%
+ \tikzexternaldisable
+ \bracketset{action character=!}%
+ \begin{forest}(stages={
+ process keylist=given options,
+ for root'={
+ sort by={>O+t+c{content}},
+ %sort=children,
+ temptoksa={},
+ for sort={children}{
+ TeX and memoize/.process=ROw2{temptoksa}{content}{####1\texttt{for\space}\index{step>####2}},
+ temptoksa={,\space},
+ },
+ }
+ })
+ [!\bigbadforlist[nodewalk][nodewalk'][Nodewalk]]
+ \end{forest}%
+ }%
+}%
+\makeatletter
+\forest at memoize\printbigbadforlist
+\makeatother
+
+{\tolerance=10000
+Here's the big list of all spatial propagators built with prefix |for|:
+% to update,
+% - uncomment \appto\bigbadforlist{[#1]} in define long step in forest.dtx
+% - delete line \forest at memo@load {forest at memo@\printbigbadforlist ... in forest-doc.memo
+\printbigbadforlist{}.
+For details on nodewalk steps, see \S\ref{ref:nodewalks}.
+
+}
+
\indexitem{propagator>for tree'}|=|\meta{keylist 1}\meta{keylist 2} A ``combination'' of
\index{for step=\index{tree children-first}} and \index{for step=\index{tree}}.
@@ -2398,11 +2623,13 @@
\item Use this key carefully as it can change the current node!
\item The envisioned purpose of this key is to change the current node within the every-step
keylist of (an outer) nodewalk, where only node keys are accepted. The config defaults
- (independent every-step, shared history) are set to facilitate that purpose.
+ (independent every-step, shared history) are set to facilitate that purpose. But it can also be
+ used as a simple node key, of course.
\end{advise}
-\indexitem{node key>node walk}|=|\meta{node walk} \textbf{Deprecated!!!} Please use \index{for
- step=\index{nodewalk}} in new code. From the old documentation:
+\indexitem{node key>node walk}|=|\meta{node walk} \textbf{Deprecated!!!} Requires
+ \index{compat}|=1.0-nodewalk|. Please use \index{for step=\index{nodewalk}} in new code. From the
+ old documentation:
\begin{quote}
This is the most general way to use a \meta{node walk}.
@@ -2491,6 +2718,10 @@
not need to be doubled: you can freely copy and paste your keylists between the node options of
the root node, the preamble and the default preamble. The only difference will be the order of
execution: first default preamble, then preamble, and finally the root node's options.
+
+\indexitem{node key>save and restore register}|=|\meta{register}\meta{keylist}
+
+Restores the current value of \meta{register} after executing the \meta{keylist}.
\indexitem{node key>split}|=|\meta{toks}\meta{separator}\meta{keylist}
\itemnosep
@@ -2502,14 +2733,42 @@
\meta{separator} (which must be a single token), and process the keys in \meta{keylist} with the
pieces of the split token list as arguments, in the order given.
- The keys in \meta{keylist} can be any valid keys, including augmented assignments, non-current
- option assignments, even \index{TeX}.
+\meta{option} can be either a simple \meta{option name} or a \meta{relative node name}\texttt{.}\meta{option name}.
The difference in the number of split values and given keys is handled gracefully. If there is
not enough values, the superfluous keys are not processed; if there are too many values, the last
key is called repeatedly.
- For an example, see \S\ref{sec:example-decision-tree}.
+ The keys in \meta{keylist} can be any valid keys, including augmented assignments, non-current
+ option assignments, even \index{TeX} or user-defined styles. Actually, as |split| works by simply
+ appending |={|\meta{current value}|}| to the relevant given key, it is possible for the key to be
+ a (sub)keylist ending in a simple, non-valued key, like shown below.
+
+ \begin{advise}
+ \item Pay attention to |%| characters around the subkeylist. In order for it to actually function
+ as a sublist, its braces should be stripped, but this can only happen if no spaces surround it.
+ \end{advise}
+
+\begin{forestexample}[point=split option,index={delay,content,split option,process args},label=ex:split option]
+ \begin{forest}
+ [
+ {1,2,3,4}
+ [,delay={
+ ~split option~=
+ {!parent.content}
+ {,}
+ {
+ content',%
+ {content+={+},content+}%
+ },
+ tempcounta'/.process={O+n}{content},
+ content+={=},
+ content+/.register=tempcounta,
+ }
+ ]
+ ]
+ \end{forest}
+\end{forestexample}
\indexitem{node key>TeX}|=|\meta{toks: \TeX\ code} The given code is executed immediately.
@@ -2771,14 +3030,14 @@
\indexitem{node key>declare keylist}|=|\meta{option name}\meta{default value}
Declares a \meta{keylist} option.
- \indexitem{node key>declare dimen}|=|\meta{option name}\meta{pgfmath: default value}
- Declares a \meta{dimen} option.
+ \indexitem{node key>declare dimen}|=|\meta{option name}\meta{default value}
+ Declares a \meta{dimen} option. The default value is processed by \index{forestmath}.
- \indexitem{node key>declare count}|=|\meta{option name}\meta{pgfmath: default value}
- Declares a \meta{count} option.
+ \indexitem{node key>declare count}|=|\meta{option name}\meta{default value}
+ Declares a \meta{count} option. The default value is processed by \index{forestmath}.
- \indexitem{node key>declare boolean}|=|\meta{option name}\meta{pgfmath: default value}
- Declares a \meta{boolean} option.
+ \indexitem{node key>declare boolean}|=|\meta{option name}\meta{default value}
+ Declares a \meta{boolean} option. The default value is processed by \index{forestmath}.
\indexitem{node key>declare toks register}|=|\meta{register name}
Declares a \meta{toks} register.
@@ -2825,7 +3084,7 @@
afterwards has no effect in the normal course of events.
\begin{syntax}
-\indexitem({{{{{}}}}}){option>align}|=|\index{value=align>left}\OR\index{value=align>center}\OR\index{value=align>right}\OR\meta{toks: tabular header}
+\indexitem({{{{{}}}}}){option>align}|=|\index{value of=align>left}\OR\index{value of=align>center}\OR\index{value of=align>right}\OR\meta{toks: tabular header}
Creates a left/center/right-aligned multiline node, or a tabular node. In the
\index{content} option, the lines of the node should separated by |\\| and the columns (if
@@ -2836,9 +3095,9 @@
\begin{forestexample}[index={l sep,align,base}]
\begin{forest} l sep+=2ex
[special value&actual value\\\hline
- \indexdef{value=align>left}&||\texttt{@\{\}l@\{\}}\\
- \indexdef{value=align>center}&||\texttt{@\{\}c@\{\}}\\
- \indexdef{value=align>right}&||\texttt{@\{\}r@\{\}}\\
+ \indexdef{value of=align>left}&||\texttt{@\{\}l@\{\}}\\
+ \indexdef{value of=align>center}&||\texttt{@\{\}c@\{\}}\\
+ \indexdef{value of=align>right}&||\texttt{@\{\}r@\{\}}\\
,~align~=ll,draw
[top base\\right aligned, ~align~=right,~base~=top]
[left aligned\\bottom base, ~align~=left,~base~=bottom]
@@ -2869,12 +3128,12 @@
This option controls the vertical alignment of multiline (and in general, \texttt{tabular}) nodes
created with \index{align}. Its value becomes the optional argument to the \texttt{tabular}
-environment. Thus, sensible values are \indexdef{value=base>t} (the top line of the table will
-be the baseline) and \indexdef{value=base>b} (the bottom line of the table will be the baseline).
+environment. Thus, sensible values are \indexdef{value of=base>t} (the top line of the table will
+be the baseline) and \indexdef{value of=base>b} (the bottom line of the table will be the baseline).
Note that this will only have effect if the node is anchored on a baseline, like in the default
case of \index{option>anchor}|=base|.
-For readability, you can use \indexdef{value=base>top} and \indexdef{value=base>bottom} instead
+For readability, you can use \indexdef{value of=base>top} and \indexdef{value of=base>bottom} instead
of \keyname{t} and \keyname{b}. (\keyname{top} and \keyname{bottom} are still stored as
\keyname{t} and \keyname{b}.)
@@ -2994,7 +3253,7 @@
\label{ref:ref-node-position}
Most of the following options apply at stage \index{pack}. Changing them afterwards has no effect
-in the normal course of events. (Options \index{option>l}, \index{option>s}, \index{x}, \index{y} and
+in the normal course of events. (Options \index{option>l}, \index{option>s}, \index{option>x}, \index{y} and
\index{option>anchor} are exceptions; see their documentation for details).
\begin{syntax}
@@ -3033,19 +3292,19 @@
\let\outerleftmargin\leftmargin
\begin{syntax}
- \item\keyname{calign}|=|\indexdef{value=calign>child} s-aligns the node anchors of the parent and
+ \item\keyname{calign}|=|\indexdef{value of=calign>child} s-aligns the node anchors of the parent and
the primary child.
- \item\keyname{calign}|=|\indexdef{value=calign>child edge} s-aligns the parent anchor of the parent
+ \item\keyname{calign}|=|\indexdef{value of=calign>child edge} s-aligns the parent anchor of the parent
and the child anchor of the primary child.
- \item \keyname{calign}|=|\indexdef{value=calign>first} is an abbreviation for
+ \item \keyname{calign}|=|\indexdef{value of=calign>first} is an abbreviation for
|calign=child,calign_child=1|.
- \item \keyname{calign}|=|\indexdef{value=calign>last} is an abbreviation for
+ \item \keyname{calign}|=|\indexdef{value of=calign>last} is an abbreviation for
|calign=child,calign_child=-1|.
- \item\keyname{calign}|=|\indexdef{value=calign>midpoint} s-aligns the parent's node anchor and the
+ \item\keyname{calign}|=|\indexdef{value of=calign>midpoint} s-aligns the parent's node anchor and the
midpoint between the primary and the secondary child's node anchor.
- \item\keyname{calign}|=|\indexdef{value=calign>edge midpoint} s-aligns the parent's parent anchor
+ \item\keyname{calign}|=|\indexdef{value of=calign>edge midpoint} s-aligns the parent's parent anchor
and the midpoint between the primary and the secondary child's child anchor.
- \item \keyname{calign}|=|\indexdef{value=calign>center} is an abbreviation for\\
+ \item \keyname{calign}|=|\indexdef{value of=calign>center} is an abbreviation for\\
|calign=midpoint,| |calign_primary_child=1,| |calign_secondary_child=-1|.
\begin{forestexample}
\begin{forest}
@@ -3054,12 +3313,12 @@
[last,calign=last[A][B][C]][8]]
\end{forest}
\end{forestexample}
- \item\keyname{calign}|=|\indexdef{value=calign>fixed angles}: The angle between the direction of
+ \item\keyname{calign}|=|\indexdef{value of=calign>fixed angles}: The angle between the direction of
growth at the current node (specified by option \index{grow}) and the line through the node
anchors of the parent and the primary/secondary child will equal the primary/secondary angle.
To achieve this, the block of children might be spread or further distanced from the parent.
- \item\keyname{calign}|=|\indexdef{value=calign>fixed edge angles}: The angle between the direction of
+ \item\keyname{calign}|=|\indexdef{value of=calign>fixed edge angles}: The angle between the direction of
growth at the current node (specified by option \index{grow}) and the line through the
parent's parent anchor and the primary/secondary child's child anchor will equal the
primary/secondary angle.
@@ -3124,9 +3383,9 @@
\box\codebox}
\begin{itemize}
- \item\keyname{fit}|=|\indexdef{value=fit>tight}: an exact boundary of the node's subtree is computed,
+ \item\keyname{fit}|=|\indexdef{value of=fit>tight}: an exact boundary of the node's subtree is computed,
resulting in a compactly packed tree. Below, the boundary of subtree L is drawn.
-\begin{forestexample}[point={fit,tight},index={fit,{value=fit>tight},delay,for step,tree,option>name,content,pgfmath}]
+\begin{forestexample}[point={fit,tight},index={fit,{value of=fit>tight},delay,for step,tree,option>name,content,pgfmath}]
\begin{forest}
delay={for tree={name/.pgfmath=content}}
[root
@@ -3141,9 +3400,9 @@
\tikz at addmode{\pgfsyssoftpath at setcurrentpath#1}%
\appto\tikz at preactions{\let\tikz at actions@path#1}%
}}\makeatother
-\item\keyname{fit}|=|\indexdef{value=fit>rectangle}: puts the node's subtree in a rectangle and effectively
+\item\keyname{fit}|=|\indexdef{value of=fit>rectangle}: puts the node's subtree in a rectangle and effectively
packs this rectangle; the resulting tree will usually be wider.
-\begin{forestexample}[point={fit,rectangle},index={fit,{value=fit>rectangle},delay,for step,tree,option>name,content,pgfmath}]
+\begin{forestexample}[point={fit,rectangle},index={fit,{value of=fit>rectangle},delay,for step,tree,option>name,content,pgfmath}]
\begin{forest}
delay={for tree={name/.pgfmath=content}}
[root
@@ -3154,9 +3413,9 @@
]
\end{forest}
\end{forestexample}
-\item\keyname{fit}|=|\indexdef{value=fit>band}: puts the node's subtree in a rectangle of ``infinite
+\item\keyname{fit}|=|\indexdef{value of=fit>band}: puts the node's subtree in a rectangle of ``infinite
depth'': the space under the node and its descendants will be kept clear.
-\begin{forestexample}[point={fit,band},index={fit,{value=fit>band},delay,for step,tree,option>name,content,pgfmath}]
+\begin{forestexample}[point={fit,band},index={fit,{value of=fit>band},delay,for step,tree,option>name,content,pgfmath}]
\begin{forest}
delay={for tree={name/.pgfmath=content}}
[root
@@ -3439,9 +3698,9 @@
\begin{forest}
for tree={~parent anchor~=south,~child anchor~=north}
[VP[V][DP]]
- \path[fill=red] (.parent anchor) circle[radius=2pt]
- (!1.child anchor) circle[radius=2pt]
- (!2.child anchor) circle[radius=2pt];
+ \path[fill=red] (.parent anchor) circle[radius=2pt];
+ \path[fill=blue] (!1.child anchor) circle[radius=2pt]
+ (!2.child anchor) circle[radius=2pt];
\end{forest}
\end{forestexample}
@@ -3468,8 +3727,7 @@
value via a |pgfmath| expression.
If the given alias clashes with an existing node name, |alias| will yield an error, while |alias'|
- will silently rename the node with this name to its default (|node@|\meta{id}) value. Use an
- empty argument to reset the node's name to its default value.
+ will silently rename the node with this name to its default value (|node@|\meta{id}).
Aliases can be used as the \meta{forest node name} part of a relative node name and as the
argument to the \index{step>name} step of a node walk. The latter includes the usage
@@ -3501,7 +3759,7 @@
In |pgfmath| expressions, this option is accessible as |n__|.
-\indexitem(node@\meta{id}){option>name}|=|\meta{toks}
+\indexitem{option>name}|=|\meta{toks} \hfill \texttt{node@}\meta{id}
\itemnosep
\indexitem{node key>name'}|=|\meta{toks} Sets the name of the node.
@@ -3587,11 +3845,12 @@
\indexitem({{{{{}}}}}){option>tikz}|=|\meta{toks: \TikZ; code} ``Decorations.''
- The code given as the value of this option will be included in the |tikzpicture| environment
- used to draw the tree. The code given to various nodes is appended in a depth-first,
- parent-first fashion. The code is included after all nodes of the tree have been drawn, so it
- can refer to any node of the tree. Furthermore, relative node names can be used to refer to
- nodes of the tree, see \S\ref{ref:relative-node-names}.
+ The code given as the value of this option will be included in the |tikzpicture| environment used
+ to draw the tree. By default, the code is included after all nodes of the tree have been drawn,
+ so it can refer to any node of the tree (furthermore, relative node names can be used to refer to
+ nodes of the tree, see \S\ref{ref:relative-node-names}) and the code given to various nodes is
+ appended in a depth-first, parent-first fashion. See \S\ref{sec:draw-tree} for details and
+ customization.
By default, bracket parser's afterthoughts feed the value of this option. See
\index{afterthought}.
@@ -3610,10 +3869,11 @@
which first steps to the parent of the \emph{origin} node, then to its grandparent and finally to
the second child of the origin's grandparent.
-The origin of the nodewalk depends on how the nodewalk is invoked. When used after the \index>{!} in a
-relative node name (\S\ref{ref:relative-node-names}), the origin is the node with the name given
-before \index>{!}; when invoked by a spatial propagator such as \index{for step=\index{nodewalk}}
-(\S\ref{ref:spatial-propagators}), the origin is the current node.
+The origin of the nodewalk depends on how the nodewalk is invoked. When used after the \index>{!}
+in a relative node name (\S\ref{ref:relative-node-names}), the origin is the node with the name
+given before \index>{!}; when invoked by a spatial propagator such as \index{for
+ step=\index{nodewalk}} (\S\ref{ref:spatial-propagators}), the origin is the current node; when
+invoked within another (outer) nodewalk, the origin is the current node of the outer nodewalk.
Formally, a \meta{nodewalk} is a list of |pgfkeys| key--value pairs. Steps in a nodewalk are thus
separated by commas. However, \foRest; also recognizes \emph{short-form} steps, whose names consist
@@ -3662,21 +3922,21 @@
from \index{path>forest} path, \foRest; would spend way too much time checking if a given node
option is actually a short-form nodewalk.
- If you need to execute nodewalk keys within the every-step keylist, use node key
- \index{node key>Nodewalk}.} which get executed after each step of the nodewalk. The every-step
-keylist of the current nodewalk is contained in register \index{register>every step} and can be
-changed at any point during the nodewalk. Its value at the start of the nodewalk depends on how the
-nodewalk was invoked. In most cases (e.g.\ \index{step>nodewalk} or prefix
-\index{for step}-based spatial propagators), it is given explicitely as an argument to the key
-that executes the nodewalk. However, see \index{step>Nodewalk} for information on how the
-every-step keylist of an embedded nodewalk can interact with the every-step keylist of its parent
-nodewalk.
+ If you need to execute nodewalk keys within the every-step keylist, use node key \index{node
+ key>Nodewalk}.} which get executed after each step of the nodewalk. The every-step keylist of
+the current nodewalk is contained in register \index{register>every step} and can be changed at any
+point during the nodewalk. Its value at the start of the nodewalk depends on how the nodewalk was
+invoked. In most cases (e.g.\ \index{step>nodewalk} or prefix \index{for step}-based spatial
+propagators), it is given explicitely as an argument to the key that executes the nodewalk.
+However, see \index{step>Nodewalk} option \index{option of=Nodewalk>every step} for information on
+how the every-step keylist of an embedded nodewalk can interact with the every-step keylist of its
+parent nodewalk.
Each nodewalk step can be either \emph{real} or \emph{fake}. Fake steps only change the current
node. Real steps also trigger execution of the every-step keylist and update of history. Fake
steps are sometimes useful as a ``computational tool''. They can be introduced explicitely using
-\index{nodewalk key>fake}; some other keys (like some history nodewalk keys, \S\ref{ref:nodewalk-history})
-introduce fake steps implicitely.
+\index{nodewalk key>fake}; some other keys (like several history nodewalk keys,
+\S\ref{ref:nodewalk-history}) introduce fake steps implicitely.
In some cases, the nodewalk might step ``out of the tree''. (Imagine using \index{step>parent} at the
root of the tree, or \index{readonly option>n}|=42| at a node with less that 42 children.) Our official term will
@@ -3686,20 +3946,204 @@
Nodewalks can be hard to follow, especially when designing styles. \FoRest; does its best to
help. First, it logs the nodewalk stack in case of error. Second, if package option
-\index{debug} is given, it logs every step made.
+\index{debug}|=|\index{option of=debug>nodewalks} is given, it logs every step made.
+\subsubsection{Invoking (embedded) nodewalks}
+\label{ref:embedded-walks}
+
+There are many ways to invoke a nodewalk. For example, several keys, like \index{fit to}, and
+aggregate functions (\S\ref{ref:aggregate-functions}) expect a \meta{nodewalk} argument. This
+section lists keys which can be used to explicitely invoke a nodewalk.
+
+The keys in this section can be used not only as node keys (in fact, not all of them can be used
+so), but also as nodewalk keys. The latter fact means that they can be used to introduce embedded
+nodewalks, which (can) have its own every-step keylist, history and on-invalid mode; for details on
+how these properties of outer and embedded nodewalk can interact, see \index{step>Nodewalk}. There
+is no limit to the depth of nodewalks embedding (nodewalk within nodewalk within nodewalk \dots).
+
+An embedded nodewalk functions as a single, fake step of the outer nodewalk. Specifically, this
+means that, while stepping through the embedded nodewalk, the every-step keylist of the outer
+nodewalk is not executed. Furthermore, by default, modifying the every-step keylist of the inner
+walk (by manipulating register \index{register>every step}) does not influence the outer nodewalk
+(but see option \index{option of=Nodewalk>every step}).
+
+An embedded nodewalk does not count as a (real, every-step keyslist invoking) step of the outer
+nodewalk. After it is finished, there are two options with respect to the new current node of the
+outer nodewalk,\footnote{Even the outermost explicitly invoked nodewalks actually have the outer
+ nodewalk. It is ``static'' in the sense that no real step is ever made in it, but it has all the
+ nodewalk properties --- the current node, \index{register>every step} keylist register, \index{option
+ of=Nodewalk>history} and \index{option of=Nodewalk>on invalid} mode (error) --- which can
+ interact with the embedded nodewalk.} depending on whether the embedded nodewalk was invoked using
+a variant of the key with or without the \index{for step} prefix (all keys in this section have the
+\index{for step} variant).
+\begin{itemize}
+\item For keys \emph{without} the \index{for step} prefix, the current node of the outer nodewalk
+ changes, \emph{via a fake step}, to the final node visited by the embedded nodewalk. This holds
+ even if the final node was reached as a fake step and even if it is invalid
+ (\index{option>id}|=0|). The fake step in the outer nodewalk cannot be made real, not even by
+ \index{nodewalk key>real}: if you want to execute the every-step keylist of the outer nodewalk at
+ the finishing node of the embedded nodewalk, follow the latter by step \index{current}.
+\item For keys \emph{with} the \index{for step} prefix, the current node of the outer nodewalk
+ remains unchanged. For this reason, the \index{for step}-prefixed keys are available as node keys
+ (we call them spatial propagators, \S\ref{ref:spatial-propagators}), while the steps without this
+ prefix are generally not, with the sole exception of \index{step>Nodewalk}, which I advise to use
+ carefully.
+\end{itemize}
+
+All steps described in this section can be prefixed by \index{for step}. All of them, with or
+without this prefix, are available as nodewalk keys. The list of keys from this section which are
+available as node keys: \index{step>Nodewalk}, \index{for step=\index{step>Nodewalk}}, \index{for
+ step=\index{nodewalk}}; you will most often want to use the latter.
+
+
+\begin{syntax}
+\indexitem{step>Nodewalk}|=|\meta{keylist: config}\meta{nodewalk}\meta{keylist: every-step}
+
+ Walks an \meta{nodewalk} starting at the current node.
+
+ This is the most generic form of embedding a nodewalk. Unlike other keys described in this
+ subsection, it can also be used as a node key even without the \index{for step} prefix, but take
+ care as it will, in general, change the current node.
+
+ The \meta{config} argument serves to specify the interaction between the outer and embedded
+ nodewalk. It can contain the following keys:
+
+ \let\outerleftmargin\leftmargin
+ \begin{syntax}
+ \indexitem(independent){option of=Nodewalk>every step}|={|\alternative{independent,inherited,shared}|}|
+ \indexitem(shared){option of=Nodewalk>history}|={|\alternative{independent,inherited,shared}|}|
+
+ The following table shows what happens to the every-step keylist and history depending on the
+ value of \keyname{every step} and \keyname{history}, respectively. State B is \meta{every-step}
+ for every step and empty for history.
+
+ \begin{tabular}{l|ccc}
+ &\keyname{independent}&\keyname{inherited}&\keyname{shared}\\\hline
+ state of the outer nodewalk&A&A&A\\
+ initial state of the inner nodewalk&B&A&A\\
+ \dots\\
+ final state of the inner nodewalk&C&C&C\\
+ state of the outer nodewalk&A&A&C
+ \end{tabular}
+ \end{syntax}
+
+ As shown in the table above, argument \meta{every-step} is used to initialize the
+ embedded nodewalk's every-step keylist when it is independent of the outer nodewalk. In other
+ cases, this argument is ignored (use |{}|).
+
+ \begin{syntax}
+ \indexitem(inherited){option of=Nodewalk>on invalid}|={|\alternative{error,fake,error in real,last valid,inherited}|}|
+
+ Like \index{nodewalk key>on invalid}, but local to this nodewalk. The additional alternative
+ \indexdef{value of=on invalid>inherited} (which is the default) means to retain the current
+ value, regardless of how it was set (by an outer nodewalk, explicit \index{nodewalk key>on
+ invalid}, or the package default, \index{value of=on invalid>error}).
+ \end{syntax}
+
+ \begin{advise}
+ \item Use \index{node key>Nodewalk} if you need to execute nodewalk keys within the every-step
+ keylist.
+ \end{advise}
+
+\begin{forestexample}[index={register>every step}]
+ \begin{forest}
+ for 2=calign with current, for children={for descendants={circle,draw}}
+ [every step,
+ [independent,for nodewalk={
+ 1,Nodewalk={~every step=independent~}{1,every step=fill,1}{},1
+ }{draw=red},
+ [[[[]]]]]
+ [inherited,for nodewalk={
+ 1,Nodewalk={~every step=inherited~}{1,every step=fill,1}{},1
+ }{draw=red},
+ [[[[]]]]]
+ [shared,for nodewalk={
+ 1,Nodewalk={~every step=shared~}{1,every step=fill,1}{},1
+ }{draw=red},
+ [[[[]]]]]]
+ \end{forest}
+\end{forestexample}
+
+
+\begin{forestexample}[index={history,walk back}]
+ \begin{forest}
+ mark/.style={tempcounta+=1,content+/.register=tempcounta,content+={,}},
+ [history:\\effect on the,align=center
+ [inner nodewalk
+ % uncommenting this would result in an error:
+ % [independent, delay={for nodewalk={
+ % tempcounta=0,111,
+ % Nodewalk={history=independent}{walk back=2}{mark,fill=yellow}
+ % }{mark,draw=red}},
+ % [[[]]]]
+ [inherited\\or\\shared, align=center,delay={for nodewalk={
+ tempcounta=0,111,
+ Nodewalk={~history=inherited~}{walk back=2}{mark,fill=yellow}
+ }{mark,draw=red}},
+ [[[]]]]]
+ [outer nodewalk
+ [inherited,delay={for nodewalk={
+ tempcounta=0,111,
+ Nodewalk={~history=inherited~}{11}{mark,fill=yellow},
+ walk back=2
+ }{mark,draw=red}},
+ [[[[[]]]]]]
+ [shared,delay={for nodewalk={
+ tempcounta=0,111,
+ Nodewalk={~history=shared~}{11}{mark,fill=yellow},
+ walk back=2
+ }{mark,draw=red}},
+ [[[[[]]]]]]]]
+ \end{forest}
+\end{forestexample}
+
+\indexitem{step>nodewalk}|=|\meta{nodewalk}\meta{keylist: every-step}
+
+ This key is a shorthand for
+
+ \begin{center}
+ \index{step>Nodewalk}|={|\index{option of=Nodewalk>every step}|=independent,|\index{option
+ of=Nodewalk>history}|=independent,|\index{option of=Nodewalk>on
+ invalid}|=inherited}|\meta{nodewalk}\meta{keylist: every-step}
+ \end{center}
+
+ \begin{advise}
+ \item \index{for step=\index{nodewalk}} is the most common way to explicitely invoke a nodewalk from a
+ node keylist (the keylist immediately following the content of the node).
+ \end{advise}
+
+\indexitem{step>nodewalk'}|=|\meta{nodewalk}
+
+ This key is a shorthand for
+
+ \begin{center}
+ \index{step>Nodewalk}|={|\index{option of=Nodewalk>every step}|=inherited,|\index{option
+ of=Nodewalk>history}|=independent,|\index{option of=Nodewalk>on
+ invalid}|=inherited}|\meta{nodewalk}|{}|
+ \end{center}
+
+ \begin{advise}
+ \item Using this key, it is easy to ``\emph{temporarily} change'' the \index{register>every step}
+ keylist of a nodewalk.
+ \item Using \index{for step=\index{nodewalk'}} is probably the easiest way to make a ``trip''
+ within a nodewalk, i.e.\ walk some steps but return to their origin afterwards.
+ \item This key (with or without the \index{for step} prefix) is not available as a node key --- it
+ would make little sense there, as it has no every-step keylist argument.
+ \end{advise}
+
+\end{syntax}
+
+
\subsubsection{Single-step keys}
\label{ref:single-step-keys}
-Single-step nodewalk keys visit a single node. If the node a single-step is trying to visit does
-not exist, the current node is set to the invalid node (i.e.\ node with \index{readonly option>id}|=0|). This
-can be useful for looping, see \S\ref{ref:loops}. Use \index{last valid} or \index{last valid'}
-to return to the node that was current before the ``unsuccessful'' single-step.
+Single-step nodewalk keys visit a single node. The behaviour in the situation when the target node
+does not exist is determined by \index{nodewalk key>on invalid}.
-For each single-step key, propagator \index{for step=\meta{step}} is also defined.
+For each single-step key, spatial propagator \index{for step=\meta{step}} is also defined.
\index{for step=\meta{step}}|=|\meta{keylist} is equivalent to
-\index{propagator>for}|={|\meta{step}|}{|\meta{keylist}|}|. If the step takes an argument, then its
+\index{for step=\index{nodewalk}}|={|\meta{step}|}{|\meta{keylist}|}|. If the step takes an argument, then its
\index{for step=\meta{step}} propagator takes two and the argument of the step precedes the
\meta{keylist}. See also \S\ref{ref:spatial-propagators}.
@@ -3851,6 +4295,16 @@
the children within each level, but the levels are still traversed from the highest to the
deepest.
+\indexitem{step>leaves}
+
+ Visits all the leaves in the current node's subtree.
+
+\indexitem[index key={level-}]{step>-level}|=|\meta{count}
+\itemnosep
+\indexitem[index key={level-'}]{step>-level'}|=|\meta{count}
+
+Visits all the nodes \meta{count} levels above the leaves in the current node's subtree.
+
\indexitem[+print form=\spaces{12},print form+=\spaces{9}]{step>preceding siblings}\quad\quad
\indexdef[+print form=\spaces{12}]{step>following siblings}%
\itemnosep
@@ -3890,199 +4344,111 @@
\end{syntax}
-\subsubsection{Embedded nodewalks}
-\label{ref:embedded-walks}
-An embedded nodewalk is a nodewalk within a nodewalk. The embedded nodewalk has its own every-step
-keylist. While stepping through the inner nodewalk, the every-step keylist of the outer nodewalk is
-not executed. Modifying the every-step keylist of the inner walk (by \index{register>every step}) does not
-influence the outer nodewalk.
+\subsubsection{Operations}
+\label{ref:nodewalk-operations}
-After the embedded nodewalk finished, its final current node becomes the current node of the outer
-nodewalk. This is true even if the final node was reached by a fake step.
+Generally speaking, nodewalk operations take an \emph{input nodewalk} and transform it into
+an \emph{output nodewalk}, while possibly also having side effects.
-\begin{advise}
-\item As node keys can be used within nodewalks, one can use spatial propagators
- (\S\ref{ref:spatial-propagators}) like \index{for step=\index{step>nodewalk}} to embed a nodewalk
- which (silently) returns to the current node of the outer nodewalk.
-\end{advise}
+The most important categorization of operations is in terms of the input nodewalk:
+\begin{itemize}
+\item ``Normal'' keys execute the input nodewalk ``invisibly'', i.e.\ with a every-step keylist that
+ is initially empty. However, even such an ``invisible'' nodewalk might not always be completely
+ without effect. For example, the effects of any node keys contained in the input nodewalk or
+ modifications of its (initially empty) every-step keylist will be felt.
+\item Most of the operation keys have the |walk_and_...| variant, where input given nodewalk is meant to
+ be ``visible'': it is walked directly in the context of the invoking nodewalk (specifically, with
+ its every-step keylist in effect).
+\item Some operation keys have the |..._in_nodewalk| variant, which operates on the portion of the
+ current nodewalk that was already walked.
+\item \index{load} has no input nodewalk.
+\end{itemize}
+All operation keys except |..._in_nodewalk| variants can be prefixed by \index{for step} to create a
+spatial propagator (\S\ref{ref:spatial-propagators}).
-An embedded nodewalk does not count as a step of the outer nodewalk (except if noted otherwise, see
-\index{group}). This means that the every-step keylist of the outer nodewalk is not executed at
-the final node of the embedded nodewalk. In other words, the step made by the embedded nodewalk as
-a unit is fake.
+The output nodewalk is always walked in the context of the invoking nodewalk. However, note that,
+as mentioned above, in the case of |walk_and_...| variants, that context can be changed during the
+execution of the input nodewalk.
-Embedded nodewalks also have their own origin and history. Nodewalks can be nested to an arbitrary
-level.
+Trivia: \index{save} is the only operation with no output nodewalk and also the only operation with
+a ``side effect'' (of saving the nodewalk, obviously).
+For some operations (\index{filter} and \index{branch}), the every-step keylist contains instructions
+on how collect the relevant information. While you can safely append and prepend to
+\index{register>every step} keylist of their input nodewalk, you should not completely rewrite
+it. If you want the operations to actually work, of course.
+
\begin{syntax}
-\indexitem{step>Nodewalk}|=|\meta{keylist: config}\meta{nodewalk}\meta{keylist: every-step}
+\indexitem{step>group}|=|\meta{nodewalk}
- Walks an (embedded) \meta{nodewalk} starting at the current node.
+ Treat \meta{nodewalk} as a single step of the (outer) nodewalk, i.e.\ the outer every-step keylist
+ is executed only at the end of the embedded nodewalk. The embedded \meta{nodewalk} inherits
+ history from the outer nodewalk. Using this key is equivalent to writing
+ \begin{center}
+ \index{step>Nodewalk}|={|\index{option of=Nodewalk>every step}|=independent,|\index{option
+ of=Nodewalk>history}|=inherited}|\meta{nodewalk}|{}, current|
+ \end{center}
- From the perspective of the outer nodewalk, the embedded nodewalk is an (implicitely) fake step
- (and cannot be made real by \index{real}): the last node visited by the embedded
- \meta{nodewalk} becomes the new current node of the outer nodewalk, even if it is invalid.
+
+ \indexitem{step>reverse}|=|\meta{nodewalk}
+ \itemnosep
+ \indexitem{step>walk and reverse}|=|\meta{nodewalk}
- The \meta{config} argument serves to specify the interaction between the outer and embedded
- nodewalk. It can contain the following keys:
+ Visits the nodes of the given \meta{nodewalk} in the reversed order.
- \let\outerleftmargin\leftmargin
- \begin{syntax}
- \indexitem(independent){option of=Nodewalk>every step}|={|\alternative{independent,inherited,shared}|}|
- \indexitem(shared){option of=Nodewalk>history}|={|\alternative{independent,inherited,shared}|}|
-
- The following table shows what happens to the every-step keylist and history depending on the
- value of \keyname{every step} and \keyname{history}, respectively. State B is \meta{every-step}
- for every step and empty for history.
-
- \begin{tabular}{l|ccc}
- &\keyname{independent}&\keyname{inherited}&\keyname{shared}\\\hline
- state of the outer nodewalk&A&A&A\\
- initial state of the inner nodewalk&B&A&A\\
- \dots\\
- final state of the inner nodewalk&C&C&C\\
- state of the outer nodewalk&A&A&C
- \end{tabular}
- \end{syntax}
-
- As shown in the table above, argument \meta{every-step} is used to initialize the
- embedded nodewalk's every-step keylist when it is independent of the outer nodewalk. In other
- cases, this argument is ignored (use |{}|).
-
- \begin{syntax}
- \indexitem(inherited){option of=Nodewalk>on invalid}|={|\alternative{error,fake,step,inherited}|}|
-
- Like \index{nodewalk key>on invalid}, but local to this nodewalk. The additional alternative
- \indexdef{value=on invalid>inherited} (which is the default) means to behave as specified by
- \index{nodewalk key>on invalid} (or the package default, \index{value=on invalid>error}, if no
- \index{nodewalk key>on invalid} was given).
- \end{syntax}
+ \indexitem{step>unique}|=|\meta{nodewalk}
-\begin{forestexample}
- \begin{forest}
- for 2=calign with current, for children={for descendants={circle,draw}}
- [every step,
- [independent,for nodewalk={
- 1,Nodewalk={~every step=independent~}{1,every step=fill,1}{},1}{draw=red},
- [[[[]]]]]
- [inherited,for nodewalk={
- 1,Nodewalk={~every step=inherited~}{1,every step=fill,1}{},1}{draw=red},
- [[[[]]]]]
- [shared,for nodewalk={
- 1,Nodewalk={~every step=shared~}{1,every step=fill,1}{},1}{draw=red},
- [[[[]]]]]]
- \end{forest}
-\end{forestexample}
+ Walks the \meta{nodewalk}, but visits each node at most once.
-
-\begin{forestexample}
- \begin{forest}
- mark/.style={tempcounta+=1,content+/.register=tempcounta,content+={,}},
- [history:\\effect on the,align=center
- [inner nodewalk
- % uncommenting this would result in an error:
- % [independent, delay={for nodewalk={
- % tempcounta=0,111,
- % Nodewalk={history=independent}{walk back=2}{mark,fill=yellow}
- % }{mark,draw=red}},
- % [[[]]]]
- [inherited\\or\\shared, align=center,delay={for nodewalk={
- tempcounta=0,111,
- Nodewalk={~history=inherited~}{walk back=2}{mark,fill=yellow}
- }{mark,draw=red}},
- [[[]]]]]
- [outer nodewalk
- [inherited,delay={for nodewalk={
- tempcounta=0,111,
- Nodewalk={~history=inherited~}{11}{mark,fill=yellow},
- walk back=2
- }{mark,draw=red}},
- [[[[[]]]]]]
- [shared,delay={for nodewalk={
- tempcounta=0,111,
- Nodewalk={~history=shared~}{11}{mark,fill=yellow},
- walk back=2
- }{mark,draw=red}},
- [[[[[]]]]]]]]
- \end{forest}
-\end{forestexample}
-
-\indexitem{step>nodewalk}|=|\meta{nodewalk}\meta{keylist: every-step}
+\indexitem{step>filter}|=|\meta{nodewalk}\index{forestmath=condition}
- This key is a shorthand for
+Visit the nodes of the given \meta{nodewalk} for which the given \meta{condition} is true.
- \begin{center}
- \index{step>Nodewalk}|={|\index{option of=Nodewalk>every step}|=independent,|\index{option of=Nodewalk>history}|=independent}|\meta{nodewalk}\meta{keylist: every-step}
- \end{center}
-
\begin{advise}
- \item \index{for step=\index{nodewalk}} is also defined.
+ \item You can safely append and prepend to \index{register>every step} keylist during the input
+ \meta{nodewalk}, but you should not completely rewrite it.
\end{advise}
-
-\indexitem{step>nodewalk'}|=|\meta{nodewalk}
- This key is a shorthand for
- \begin{center}
- \index{step>Nodewalk}|={|\index{option of=Nodewalk>every step}|=inherited,|\index{option of=Nodewalk>history}|=independent}|\meta{nodewalk}\meta{keylist: every-step}
- \end{center}
-
- \begin{advise}
- \item \index{for step=\index{nodewalk'}} is also defined.
- \end{advise}
-
-\indexitem{step>group}|=|\meta{nodewalk}
+\indexitem{step>branch}|={|\meta{nodewalk$_1$}|,...,|\meta{nodewalk$_n$}|}|
+ \itemnosep
+\indexitem{step>branch'}|={|\meta{nodewalk$_1$}|,...,|\meta{nodewalk$_n$}|}|
- Treat \meta{nodewalk} as a single step of the (outer) nodewalk, i.e.\ the outer every-step keylist
- is executed only at the end of the embedded nodewalk. The embedded \meta{nodewalk} inherits
- history from the outer nodewalk. Using this key is equivalent to writing
- \begin{center}
- \index{step>Nodewalk}|={|\index{option of=Nodewalk>every step}|=independent,|\index{option
- of=Nodewalk>history}|=inherited}|\meta{nodewalk}|{}, current|
- \end{center}
+Visit the nodes in a ``cartesian product'' of any number of nodewalks, where a cartesian product is
+defined as a nodewalk where at every step of \meta{nodewalk$_i$} ($1\leq i<n$),
+\meta{nodewalk$_{i+1}$} is executed.
+The |branch| variant visits only the nodes visited by the innermost nodewalk, \meta{nodewalk$_n$}.
+The |branch'| variant visits the nodes visited by all the nodewalks of the product,
+\meta{nodewalk$_1$} \dots\ \meta{nodewalk$_n$}.
+
+For an example of each, see \index{c-commanded} and \index{c-commanders} from the
+\reflibrary{linguistics} library.
+
\begin{advise}
- \item It is safe to modify the every-step keylist of \meta{nodewalk}.
- \item \index{for step=\index{group}} is also defined.
+ \item You can safely append and prepend to \index{register>every step} keylists during the input
+ \meta{nodewalk}s, but you should not completely rewrite them.
\end{advise}
-
-
-\end{syntax}
-\subsubsection{Operations}
-\label{ref:nodewalk-operations}
-Operations internally walk the given nodewalk (except |..._in_nodewalk| variants, which operate on
-the portion of the current nodewalk that was already walked) to gather some information about
-visited nodes. Then, based on that information, they walk some steps in the context (most
-importantly, with \index{register>every step} keylist) of the current nodewalk.
-
-Most of the following keys have a |walk_and_...| variant, which first walks the given nodewalk and
-then performs the desired operation. All operation keys except |..._in_nodewalk| variants can be
-prefixed by \index{for step}.
-
-\begin{advise}
-\item The every-step keylist of the internal nodewalk is empty; or, more precisely, it contains only
- instructions to how collect the relevant information. You can safely append and prepend to
- \index{register>every step} keylist of the internal nodewalk, but you should not completely
- rewrite it.
-\end{advise}
-
-\begin{syntax}
- \indexitem{step>reverse}|=|\meta{nodewalk}
+ \indexitem{step>save}|=|\meta{toks: name}\meta{nodewalk}
\itemnosep
- \indexitem{step>walk and reverse}|=|\meta{nodewalk}
+ \indexitem{step>walk and save}|=|\meta{toks: name}\meta{nodewalk}
- Visits the nodes of the given \meta{nodewalk} in the reversed order.
+ Saves the given \meta{nodewalk} under the given name.
- \indexitem{nodewalk key>save}|=|\meta{toks: name}\meta{nodewalk}
+ \indexitem{step>save append}|=|\meta{toks: name}\meta{nodewalk}
\itemnosep
- \indexitem{step>walk and save}|=|\meta{toks: name}\meta{nodewalk}
+ \indexitem{step>save prepend}|=|\meta{toks: name}\meta{nodewalk}
+ \itemnosep
+ \indexitem{step>walk and save append}|=|\meta{toks: name}\meta{nodewalk}
+ \itemnosep
+ \indexitem{step>walk and save prepend}|=|\meta{toks: name}\meta{nodewalk}
- Saves the given \meta{nodewalk} under the given name.
+ Appends/prepends the given \meta{nodewalk} to nodewalk \meta{name}.
\indexitem{step>load}|=|\meta{toks: name} Walks the nodewalk saved under the given name.
@@ -4090,6 +4456,7 @@
a different current node, or even with a tree whose geometry has changed (see \S\ref{ref:dynamic})
will still visit exactly the nodes that were visited when the nodewalk was saved.
+
\indexitem{step>sort}|=|\meta{nodewalk}
\itemnosep
\indexitem{step>sort'}|=|\meta{nodewalk}
@@ -4103,7 +4470,7 @@
the descending order. The \keyname{walk and sort} variants first visit the nodes in the order
specified by the given \meta{nodewalk}.
- \indexitem{node key>sort by}|={|\meta{pgfmath}|,|\dots|,|\meta{pgfmath}|}|
+ \indexitem{node key>sort by}|={|\index{forestmath}|,|\dots|,|\index{forestmath}|}|
Sets the sorting order used by all keys comparing nodes: \index{step>sort}, \index{step>min}
and \index{step>max} key families in the nodewalk namespace, and the \index{dynamic
@@ -4117,13 +4484,43 @@
Simply put, if you want to sort first by the number of children and then by content, say
|sort_by={|\index[+print format=pgfmath]{n children}|,_|\index{content}|}|.
- In the simplest case, the given \meta{pgfmath} expressions are simply node options. However, as
+ In the simplest case, the given \index{forestmath} expressions are simply node options. However, as
any |pgfmath| expression is allowed in the sort key, you can easily sort by the product of the
content of the current node and the content of its first child:
- |sort_by={|\index{content}|()*|\index{content}|("|\index>{!}|1")|. Note, however, that the value returned by these expression
- must be numeric, i.e.\ alphabetic comparison of strings is not implemented.
+ |sort_by={|\index{content}|()*|\index{content}|("|\index>{!}|1")|.
+ To sort alphabetically, one must use the argument processor (\S\ref{ref:argument-processor}) to
+ specify the sort order. In particular, the key must be marked as text using \index{processor>t}.
+ The first example below shows a simple alphabetical sort by content; the second sorts the
+ filenames by suffix first (in the ascending order) and then by the basename (in the descending
+ order, see \index{processor>-}).
+\begin{forestexample}
+ \begin{forest}
+ [,phantom,grow'=0,for children={anchor=west,child anchor=west},s sep=0,
+ delay={~sort by=>O+t{content},sort~}
+ [example.tex][example.pdf][example.log][example.aux]
+ [thesis.tex][thesis.pdf][thesis.log][thesis.aux][thesis.toc]
+ ]
+ \end{forest}
+\end{forestexample}
+
+\begin{forestexample}
+ \begin{forest}
+ declare toks={basename}{},
+ declare toks={extension}{},
+ [,phantom,grow'=0,for children={anchor=east},s sep=0,
+ delay={
+ for children={split option={content}{.}{basename,extension}},
+ ~sort by={>O+t{extension},>O+t-{basename}}~,
+ ~sort~,
+ }
+ [example.tex][example.pdf][example.log][example.aux]
+ [thesis.tex][thesis.pdf][thesis.log][thesis.aux][thesis.toc]
+ ]
+ \end{forest}
+\end{forestexample}
+
\indexitem{step>min}|=|\meta{nodewalk}, \indexdef{step>max}|=|\meta{nodewalk}
\itemnosep
\indexitem{step>walk and min}|=|\meta{nodewalk}, \indexdef{step>walk and max}|=|\meta{nodewalk}
@@ -4154,26 +4551,6 @@
node by moving back in the history, see \index{back}.
-\indexitem{step>filter}|=|\meta{nodewalk}\meta{pgfmath: condition}
-
-Visit the nodes of the given \meta{nodewalk} for which the given \meta{condition} is true.
-
-
-\indexitem{step>branch}|={|\meta{nodewalk$_1$}|,...,|\meta{nodewalk$_n$}|}|
- \itemnosep
-\indexitem{step>branch'}|={|\meta{nodewalk$_1$}|,...,|\meta{nodewalk$_n$}|}|
-
-Visit the nodes in a ``cartesian product'' of any number of nodewalks, where a cartesian product is
-defined as a nodewalk where at every step of \meta{nodewalk$_i$} ($1\leq i<n$),
-\meta{nodewalk$_{i+1}$} is executed.
-
-The |branch| variant visits only the nodes visited by the innermost nodewalk, \meta{nodewalk$_n$}.
-The |branch'| variant visits the nodes visited by all the nodewalks of the product,
-\meta{nodewalk$_1$} \dots\ \meta{nodewalk$_n$}.
-
-For an example of each, see \index{c-commanded} and \index{c-commanders} from the
-\reflibrary{linguistics} library.
-
\end{syntax}
\subsubsection{History}
@@ -4254,7 +4631,7 @@
The variant \emph{without} |'| makes a fake step. More precisely, it behaves as if both
\index{nodewalk key>fake} and \index{nodewalk key>on invalid}|=fake| are in effect.
-\indexitem(error){nodewalk key>on invalid}|={|\alternative{error,fake,step}|}|\meta{nodewalk}
+\indexitem{nodewalk key>on invalid}|={|\alternative{error,fake,step}|}|\meta{nodewalk}
This key determines what should happen if a nodewalk step landed on the invalid node, i.e.\ the node
with \index{readonly option>id}|=0|.
@@ -4265,15 +4642,19 @@
\let\outerleftmargin\leftmargin
\begin{syntax}
- \item |on invalid=|\indexdef{value=on invalid>error} produces an error;
- \item |on invalid=|\indexdef{value=on invalid>fake} does nothing: history is not updated and the
- every-step keylist is not executed, thus making the step essentialy fake;
- \item |on invalid=|\indexdef{value=on invalid>step} makes a step, either real or fake, depending
- on the environment.
+ \item |on invalid={|\indexdef{value of=on invalid>error}|}|\meta{nodewalk} produces an error;
+ \item |on invalid={|\indexdef{value of=on invalid>fake}|}|\meta{nodewalk} does nothing: history is
+ not updated and the every-step keylist is not executed, thus making the step essentialy fake;
+ \item |on invalid={|\indexdef{value of=on invalid>error if real}|}|\meta{nodewalk} produces an
+ error unless \index{nodewalk key>fake} is in effect.
+ \item |on invalid={|\indexdef{value of=on invalid>last valid}|}|\meta{nodewalk} returns to the
+ last valid node, by making a fake step, like \index{step>last valid}.
\end{syntax}
Loops with the implicit |id=0| condition (\S\ref{ref:loops}) automatically switch to
|on_invalid=fake| mode.
+
+ See also \index{step>Nodewalk} option \index{option of=Nodewalk>on invalid}.
\indexitem{nodewalk key>options}=\meta{keylist: node keys}
@@ -4317,7 +4698,7 @@
\indexitem{short step>R} the formal root node --- \index{root'}
\indexitem{short step>b} back one fake step in history --- \index{back}|=1|
\indexitem{short step>f} forward one fake step in history --- \index{forward}|=1|
-\indexitem{short step>v} last valid node in the current nodewalk, fake version --- \index{last valid}
+\indexitem{short step>v} last valid node in the current nodewalk, fake version --- \index{step>last valid}
\indexitem{short step>*}\meta{count: n}\meta{keylist} repeat keylist $n$ times --- \index{repeat}|=|\meta{count: n}\meta{keylist}
\item {\rstyle $\{$}\meta{keylist}{\rstyle $\}$} put keylist in a group --- \index{group}|=|\meta{keylist}
\end{syntax}
@@ -4342,10 +4723,10 @@
Should we make a \index{for step} prefix for the step?
\item\indexdef{option of=define long step>strip fake steps}|=|\meta{boolean}\hfill |true|
- Imagine that \meta{nodewalk} ends with fake steps. Now, fake steps are usually just a computational tool, so we normally wouldn't want the current node after the walk to be one of them. As far as the outer world is concerned, we want the node to end at the last real step. However, simply appending \index{last valid} to our style will not work. Imagine that the nodewalk results in no steps. In this case, we'd want to remain at the origin of our empty nodewalk. However, imagine further that the (outer) step just before the empty nodewalk was fake. Then \index{last valid} will not step to the correct node: instead of staying at the origin, it will go to the node that the last real step prior to our nodewalk stepped to. In case there was no such real step, we'd even step to the invalid node (normally getting an error).
+ Imagine that \meta{nodewalk} ends with fake steps. Now, fake steps are usually just a computational tool, so we normally wouldn't want the current node after the walk to be one of them. As far as the outer world is concerned, we want the node to end at the last real step. However, simply appending \index{step>last valid} to our style will not work. Imagine that the nodewalk results in no steps. In this case, we'd want to remain at the origin of our empty nodewalk. However, imagine further that the (outer) step just before the empty nodewalk was fake. Then \index{step>last valid} will not step to the correct node: instead of staying at the origin, it will go to the node that the last real step prior to our nodewalk stepped to. In case there was no such real step, we'd even step to the invalid node (normally getting an error).
Defining the step using |strip fake steps| ensures the correct behaviour described
- above. Set |strip fake steps=false| only when the fake steps at the end of the nodewalk at
+ above. Set |strip fake steps=false| only when the fake steps at the end of the nodewalk are
important to you.
\begin{advise}
@@ -4375,45 +4756,64 @@
\indexitem{handler>nodewalk style}|=|\meta{nodewalk}
-A shorthand for |for nodewalk={|\meta{nodewalk}|}{}|.
+\meta{nodewalk key}|/.nodewalk style=|\meta{nodewalk} is a shorthand for\\
+|for_nodewalk={|\meta{nodewalk key}|/.style=|\meta{nodewalk}|}{}|.
\end{syntax}
-\subsection{Conditionals and loops}
+\subsection{Conditionals}
\label{ref:conditionals}
-\label{ref:loops}
-All conditionals take arguments \meta{true keylist} and \meta{false keylist}, and all loops take an
-argument \meta{keylist}. The interpretation of the keys in these keylists depends on the
-environment the conditional/loop appears in. If it is a part of a nodewalk
-specification, the keys are taken to be nodewalk keys (\S\ref{ref:nodewalks}), otherwise node keys
-(\S\ref{ref:node-keys}).
+All conditionals take arguments \meta{true keylist} and \meta{false keylist}. The interpretation of
+the keys in these keylists depends on the environment the conditional appears in. If it is a part
+of a nodewalk specification, the keys are taken to be nodewalk keys (\S\ref{ref:nodewalks}),
+otherwise node keys (\S\ref{ref:node-keys}).
-All the loops and conditionals can be nested safely.
+All the conditionals can be nested safely.
-\begin{advise}
-\item Except in special circumstances, you probably don't want to embed keys from the \index{where
- option} family within a \index{for step=\index{tree}}, as this results in two nested loops. It
- is more usual to use an \index{conditional>if} family key there. For an example where using
- \index{where option} actually does the wrong thing, see question
- \href{http://tex.stackexchange.com/questions/167978/smaller-roofs-for-forest}{Smaller roofs for
- forest} on \TeX\ Stackexchange.
-\end{advise}
-
\begin{syntax}
-\indexitem{conditional>if}|=|\meta{pgfmath condition}\meta{true keylist}\meta{false keylist}
+\indexitem{conditional>if}|=|\index{forestmath=condition}\meta{true keylist}\meta{false keylist}
- If \meta{pgfmath condition} evaluates to |true| (non-zero), \meta{true keylist} is processed (in
+ If \index{forestmath=condition} evaluates to |true| (non-zero), \meta{true keylist} is processed (in
the context of the current node); otherwise, \meta{false keylist} is processed.
For a detailed description of |pgfmath| expressions, see \cite[part VI]{tikzpgf2.10}. (In short:
write the usual mathematical expressions.)
+ In the following example, \index{conditional>if} is used to orient the arrows from the smaller
+ number to the greater, and to color the odd and even numbers differently. (Style |random_tree| is
+ defined in the front page example.)
+
+\forestset{random tree/.style n args={3}{% #1=max levels, #2=max children, #3=max content
+ content/.pgfmath={random(0,#3)},
+ if={#1>0}{repeat={random(0,#2)}{append={[,random tree={#1-1}{#2}{#3}]}}}{}}}
+\begin{forestexample}[index={before typesetting nodes,for step,descendants,conditional>if,content,edge,edge label,tree},index>={!},point=if]
+ \pgfmathsetseed{314159}
+ \begin{forest}
+ before typesetting nodes={
+ for descendants={
+ if={content()>content("!u")}{edge=->}{
+ if={content()<content("!u")}{edge=<-}{}},
+ edge label/.wrap pgfmath arg=
+ {node[midway,above,sloped,font=\scriptsize]{+#1}}
+ {int(abs(content()-content("!u")))}
+ },
+ for tree={circle,if={mod(content(),2)==0}
+ {fill=yellow}{fill=green}}
+ }
+ [,random tree={3}{3}{100}]
+ \end{forest}
+\end{forestexample}
+
+
+
+
\indexitem{word prefix=option>conditional>if=\meta{option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
- A simple conditional is defined for every \meta{option}: if \meta{value} equals the value of the
- option at the current node, \meta{true keylist} is executed; otherwise, \meta{false keylist}.
+This simple conditional is defined for every \meta{option} (except boolean options, see below): if
+\meta{value} equals the value of the option at the current node, \meta{true keylist} is executed;
+otherwise, \meta{false keylist}.
\indexitem{word prefix=boolean option>conditional>if=\meta{boolean option}}|=|\meta{true keylist}\meta{false keylist}
@@ -4427,7 +4827,33 @@
otherwise \meta{false keylist}.
This conditional is defined only for \meta{toks} options, see \S\ref{sec:option-setting}.
+
+
+\indexitem[set={
+ index format={result=if \protect\meta{dimen option}\protect\greaterthan,pgfkey},
+ print format={result/.option=argument,+result={if\ },result+={>}, pgfkey},
+}]{conditional>if dimen GT=\protect\meta{dimen option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
+\indexitem[set={
+ index format={result=if \protect\meta{dimen option}<,pgfkey},
+ print format={result/.option=argument,+result={if\ },result+={<}, pgfkey},
+}]{conditional>if dimen LT=\protect\meta{dimen option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
+\indexitem[set={
+ index format={result=if \protect\meta{count option}\protect\greaterthan,pgfkey},
+ print format={result/.option=argument,+result={if\ },result+={>}, pgfkey},
+}]{conditional>if count GT=\protect\meta{count option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
+\indexitem[set={
+ index format={result=if \protect\meta{count option}<,pgfkey},
+ print format={result/.option=argument,+result={if\ },result+={<}, pgfkey},
+}]{conditional>if count LT=\protect\meta{count option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+
+If the current value of the dimen/count option is greater/less than or equal to \meta{value},
+execute \meta{true keylist}; else, execute \meta{false keylist}.
+
+
\indexitem{conditional>if nodewalk valid}|=|\meta{keylist: test nodewalk}\meta{true keylist}\meta{false keylist}
If the test nodewalk finished on a valid node, \meta{true keylist} is processed (in the context of
@@ -4438,8 +4864,13 @@
If the test nodewalk contains no (real) steps, \meta{true keylist} is processed (in the context of
the current node); otherwise, \meta{false keylist} is processed.
-\indexitem{conditional>if in saved nodewalk}|=|\meta{nodewalk}\meta{toks: nodewalk name}\meta{true keylist}\meta{false keylist}
+\indexitem{conditional>if current nodewalk empty}|=|\meta{true keylist}\meta{false keylist}
+ If the current nodewalk contains no (real) steps, \meta{true keylist} is processed (in the context of
+ the current node); otherwise, \meta{false keylist} is processed.
+
+ \indexitem{conditional>if in saved nodewalk}|=|\meta{nodewalk}\meta{toks: nodewalk name}\meta{true keylist}\meta{false keylist}
+
If the node at the end of \meta{nodewalk} occurs in the saved nodewalk, \meta{true keylist} is
processed (in the context of the current node); otherwise, \meta{false keylist} is processed.
@@ -4455,24 +4886,76 @@
\indexitem{propagator>if have delayed'}|=|\meta{nodewalk}\meta{true keylist}\meta{false keylist}
Like \index{if have delayed}, but assume the processing order given by \meta{nodewalk}.
+\end{syntax}
+
+
+
+The following keys are shortcuts: they execute their corresponding |if ...| conditional for every
+node in the subtree of the current node (including the node itself). In other words:
+
+\begin{center}
+ |where ...|\meta{arg$_1$}\dots\meta{arg$_n$}|/.style={for tree={if ...=|\meta{arg$_1$}\dots\meta{arg$_n$}|}}|
+\end{center}
+
+\begin{advise}
+\item Except in special circumstances, you probably don't want to embed keys from the \index{where
+ option} family within a \index{for step=\index{tree}}, as this results in two nested loops. It
+ is more usual to use an \index{conditional>if} family key there. For an example where using
+ \index{where option} actually does the wrong thing, see question
+ \href{http://tex.stackexchange.com/questions/167978/smaller-roofs-for-forest}{Smaller roofs for
+ forest} on \TeX\ Stackexchange.
+\end{advise}
+
+\begin{syntax}
\indexitem{propagator>where}|=|\meta{value}\meta{true keylist}\meta{false keylist}
\itemnosep
\indexitem{word prefix=option>conditional>where=\meta{option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
\itemnosep
+\indexitem{word prefix=boolean option>conditional>where=\meta{boolean option}}|=|\meta{true keylist}\meta{false keylist}
+\itemnosep
\indexitem{word prefix=toks option>conditional>where in=\meta{toks option}}|=|\meta{toks}\meta{true keylist}\meta{false keylist}
\itemnosep
+\indexitem[set={
+ index format={result=where \protect\meta{dimen option}\protect\greaterthan,pgfkey},
+ print format={result/.option=argument,+result={where\ },result+={>}, pgfkey},
+}]{conditional>where dimen GT=\protect\meta{dimen option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
+\indexitem[set={
+ index format={result=where \protect\meta{dimen option}<,pgfkey},
+ print format={result/.option=argument,+result={where\ },result+={>}, pgfkey},
+}]{conditional>where dimen LT=\protect\meta{dimen option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
+\indexitem[set={
+ index format={result=where \protect\meta{count option}\protect\greaterthan,pgfkey},
+ print format={result/.option=argument,+result={where\ },result+={>}, pgfkey},
+}]{conditional>where count GT=\protect\meta{count option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
+\indexitem[set={
+ index format={result=where \protect\meta{count option}<,pgfkey},
+ print format={result/.option=argument,+result={where\ },result+={>}, pgfkey},
+}]{conditional>where count LT=\protect\meta{count option}}|=|\meta{value}\meta{true keylist}\meta{false keylist}
+\itemnosep
\indexitem{step>where nodewalk valid}|=|\meta{toks: nodewalk name}\meta{true keylist}\meta{false keylist}
\itemnosep
\indexitem{step>where nodewalk empty}|=|\meta{toks: nodewalk name}\meta{true keylist}\meta{false keylist}
\itemnosep
\indexitem{step>where in saved nodewalk}|=|\meta{nodewalk}\meta{toks: nodewalk name}\meta{true keylist}\meta{false keylist}
+\end{syntax}
-These keys execute their corresponding |if ...| conditional for every node in the subtree of the current node (including the node itself). In other words:
-\begin{center}
- |where ...|\meta{arg$_1$}\dots\meta{arg$_1$}|/.style={for tree={if ...=|\meta{arg$_1$}\dots\meta{arg$_1$}|}}|
-\end{center}
+\subsection{Loops}
+\label{ref:loops}
+All loops take a \meta{keylist} argument. The interpretation of the keys in these keylists depends
+on the environment the loop appears in. If it is a part of a nodewalk specification,
+the keys are taken to be nodewalk keys (\S\ref{ref:nodewalks}), otherwise node keys
+(\S\ref{ref:node-keys}).
+
+All loops can be nested safely.
+
+
+\begin{syntax}
+
\indexitem{loop>repeat}|=|\meta{number}\meta{keylist}
The \meta{keylist} is processed \meta{number} times.
@@ -4479,13 +4962,13 @@
The \meta{number} expression is evaluated using |pgfmath|.
-\indexitem{loop>while}|=|\meta{pgfmath condition}\meta{keylist}
+\indexitem{loop>while}|=|\index{forestmath=condition}\meta{keylist}
\itemnosep
-\indexitem{loop>do while}|=|\meta{pgfmath condition}\meta{keylist}
+\indexitem{loop>do while}|=|\index{forestmath=condition}\meta{keylist}
\itemnosep
-\indexitem{loop>until}|=|\meta{pgfmath condition}\meta{keylist}
+\indexitem{loop>until}|=|\index{forestmath=condition}\meta{keylist}
\itemnosep
-\indexitem{loop>do until}|=|\meta{pgfmath condition}\meta{keylist}
+\indexitem{loop>do until}|=|\index{forestmath=condition}\meta{keylist}
\keyname{while} loops cycle while the condition is true, \keyname{until} loops terminate when the
condition becomes true.
@@ -4494,13 +4977,13 @@
keylist is executed at least once. The variants without the \keyname{do} prefix check the
condition before processing the \meta{keylist}, which might therefore not be processed at all.
- When \meta{pgfmath condition} is an empty string, condition \index{valid} is implicitely used,
+ When \index{forestmath=condition} is an empty string, condition \index{valid} is implicitely used,
and \meta{keylist} is implicitely embedded in \index{nodewalk key>on invalid}|=fake|. Thus, the |while|
loops will cycle until they ``walk out of the tree'', and |until| loops will cycle until they
``walk into the tree.''
\begin{advise}
- \item If a loop ``walks out of the tree'', you can get it back in using \index{last valid} or
+ \item If a loop ``walks out of the tree'', you can get it back in using \index{step>last valid} or
\index{nodewalk key>strip fake steps}.
\end{advise}
@@ -4535,12 +5018,19 @@
\meta{nodewalk} is embedded within \index{nodewalk key>on invalid}|=fake|.
-\indexitem(0){loop>break}|=|$n$ Break out of the loop.
+\indexitem(0){node key>break}|=|$n$ Break out of the loop.
The loop is only exited after all the keys in the current cycle have been processed.
The optional argument $n$ ($n\geq0$) specifies which level of embedding to break from; the default
is to break out of the innermost loop.
+
+\indexitem(0){pgfmath>forestloopcount}([$n$])
+
+ How many times has the loop repeated until now?
+
+ The optional argument $n$ ($n\geq0$) specifies the level of embedding to provide information for;
+ the default is to count the repetitions of the current, most deeply embedded loop.
\end{syntax}
@@ -4586,9 +5076,10 @@
\item Such a two-stage approach is employed because changing the tree structure during the dynamic
tree key processing would lead to an unmanageable order of keylist processing.
\item A consequence of this approach is that nested dynamic tree keys take several cycles to
- complete. Therefore, be careful when using \index{delay} and dynamic tree keys
- simultaneously: in such a case, it is often safer to use \index{before typesetting nodes}
- instead of \index{delay}, see example (\ref{ex:append}).
+ complete. Therefore, be careful when using \index{delay} and dynamic tree keys simultaneously: in
+ such a case, it is often safer to use \index{before typesetting nodes} instead of \index{delay},
+ see example (\ref{ex:append}), and it is also possible to define additional stages, see
+ \S\ref{sec:workflow}.
\item Examples: title page (in style |random tree|) and (\ref{ex:niceemptynodes}) (in style
|xlist|).
\end{advise}
@@ -4712,6 +5203,12 @@
\subsection{Handlers}
\label{ref:handlers}
+Handlers are a powerful mechanism of |pgfkeys|, documented in \citep[\S82.3.5]{tikzpgf3.0.0}.
+Handlers defined by \foRest; perform a computation and invoke the handled key with its result. The
+simple handlers are documented in this section: for \index{handler>process}, see
+\S\ref{ref:argument-processor}; for aggregate function handlers, see
+\S\ref{ref:aggregate-functions}.
+
\begin{syntax}
\indexitem{handler>option}|=|\meta{option}
@@ -4747,89 +5244,519 @@
Like \index{wrap $n$ pgfmath args} would work for $n=1$.
-\indexitem{handler>process args}|=|\meta{argument types}\meta{arg $1$}\dots\meta{arg $n$}
- The result is a list of processed arguments. Arguments
- are processed individually according to their given type. The types are given sequentially in
- \meta{argument types}, one character (no spaces) for each argument. The meanings of the characters are given in the table below. The exception to the one character -- one argument rule are characters
- connected by |+|, which apply iteratively (in the given order) to a single argument. If the
- argument type list is shorter than the number of argument, the remaining arguments are assumed to
- require no processing.
+\end{syntax}
+
+\subsection{Argument processor}
+\label{ref:argument-processor}
+
+For a gentle(r) introduction to the argument processor, see \S\ref{tut:wrapping}.
+
+The argument processor takes a sequence of instructions and an arbitrary number of arguments and
+transforms the given arguments according to the instructions. There are two ways to invoke the
+argument processor:
+
+\begin{syntax}
- \begin{tabular}{ll}
- |__|&no processing\\
- |o|&expand once\\
- |x|&fully expand\\
- |O|&argument is an option name\\
- |R|&argument is a register name\\
- |P|&argument is a pgfmath expression\\
- |r|&the argument should be a comma-separated list: reverse it\\
- |+|&chain processors)\\
- \end{tabular}
+\indexitem{handler>process}|=|\meta{instructions}\meta{arg $1$}\dots\meta{arg $n$}
- Example: \index{split option} is defined by preprocessing the first argument of \index{split}
- as an option.
-\lstinputregion{forest.dtx}{split_option}
+The result of the computation is passed on to the handled key as a sequence of arguments. Any
+number of arguments can be returned.\footnote{For backward compatibility, \index{handler>process} is also
+ available as \indexdef{handler>process args}.}
-\begin{forestexample}[index={delay,append,strequal,split,process args}]
+\item \indexdef{meta>forestmath} = \meta{pgfmath}\OR|>|\meta{instructions}\meta{arg
+ $1$}\dots\meta{arg $n$}
+
+ In words, a \index{forestmath} expression is either a \meta{pgfmath} expression or an argument
+ processor expression prefixed by |>|.
+
+ In other words, \FoRest; accepts an argument processor expression anywhere\footnote{The only
+ exceptions to the above rule are handler \index{pgfmath} and argument processor instruction
+ \index{processor>P}.} it accepts a \meta{pgfmath} expression. To indicate that we're providing
+ an argument processor expression, we prefix it with |>|.
+
+ The result of argument processor's computation should be a single item.
+
+\end{syntax}
+
+
+The syntax of argument processor is a cross between |expl3|'s function argument specification and a
+Turing machine, spiced with a bit of reversed Polish notation. ;-)
+
+Think of \meta{instructions} as a program and \meta{arg $1$}\dots\meta{arg $n$} as the data that
+this program operates on.
+
+If you're familiar with Turing machines: like a Turing machine, the argument processor has a notion
+of a head; unlike a Turing machine, the argument processor head is positioned not over some
+argument, but between two arguments. If you're not familiar with Turing machines: imagine the
+arguments as items on a tape and the argument processor as a head that is always located between
+some two items. As the head is between two arguments, we can talk about the arguments on the left
+and the arguments on the right.
+
+In general, an instruction will take some items from the left and some from the right (deleting them
+from the tape), perform some computation and insert the result on the tape, some result items to the
+left and some to the right. However, most instructions simply take an item from the right, do
+something with it, and put the (single-item) result to the left; in effect, the head is moved one
+item to the right. At the beggining, all the arguments are always on the right, so the general idea
+is that the program will walk through the given arguments, processing them in order.
+
+Descriptions of individual instructions, given below, contain (at the right edge of the page) the
+argument specification, which tells us about the number of input and output items and the movement
+of the head. The input and output are separated by an arrow ($\longrightarrow$), and the green eye
+(\textcolor{darkgreen}{\eye}) signifies the position of the head with respect to the (input or
+output) items.
+
+For example, instruction \index{processor>O}, which converts an option name into the option value,
+exemplifies the most common scenario: it takes one argument from the right and puts the result to
+the left (in other words, the head moves one item to the right). Wrapping instrucion
+\index{processor>w} is more complicated. Given instruction \index{processor>w}$n$, the argument
+processor takes one argument from the right (the wrapping macro body) and $n$ items from the left
+(which become the arguments of the wrapping macro), and puts the resulting item to the left.
+Comparisons and boolean operations are the instructions resembling the reverse Polish notation: they
+take the arguments from the left and put the result to the left, as well. Finally, it is worth
+mentioning instructions \index{processor>noop} and \index{processor>+}, which simply move the head
+to the right and left, respectively; given that the usual movement of the head is to the right,
+\index{processor>+} can be thought of as a process-the-argument-again instruction.
+
+
+Before we finally list the available instructions, some notes:
+\begin{itemize}
+\item \meta{Instructions} may be given in braces or not. If not, everything until the first opening
+ brace is considered to be an instruction.
+\item An argument item (\meta{arg$_k$}) is a standard \TeX\ macro argument: either a token or a
+ braced token list. (The obvious exception: \meta{arg$_1$} needs to be braced if it follows
+ braceless instructions.)
+\item Spaces in \meta{instructions} and between arguments are ignored. Format your \index{handler>process}
+ as you wish!
+\item Instructions followed by [$n$] below take an optional numeric modifier.
+ \begin{itemize}
+ \item The modifier should be given within the instruction string itself, immediately following the
+ instruction. In particular, no spaces are allowed there. (Sorry for the little white lie
+ above.) The number should not be enclosed in braces, even if it is more than one digit long.
+ \item This modifier is always optional: its default value varies from instruction to instruction.
+ (Providing $0$ means to use the default.)
+ \item Unless noted otherwise, the optional numerical argument $n$ instruct the argument processor
+ to repeat the previous instruction $n$ times (by default, 1). For example,
+ \index{processor>O}|3| is equivalent to
+ \index{processor>O}\index{processor>O}\index{processor>O}.
+ \end{itemize}
+\end{itemize}
+
+
+\NewDocumentEnvironment{indexitemprocessinstruction}{
+ D(){} % default
+ O{} % \index []
+ m % instruction char
+ D(){} % instruction modifiers
+ m % first line
+ >{\ReverseBoolean} s % typeset processor signature?
+ >{\SplitArgument {3} {&} } m % processor signature
+ o % instruction in signature
+}{%
+ \indexitem(#1)[set={#2}]{processor>#3}#4 #5%
+ \edef\ins{\noexpand\texttt{\IfNoValueTF{#8}{\detokenize{#3}}{#8}}}%
+ \IfBooleanT{#6}{\hfill\processorsignature#7}%
+
+}{}
+
+\newcommand\processorsignature[4]{%
+ #1 \textcolor{darkgreen}{\eye} #2
+ $\longrightarrow$
+ #3 \textcolor{darkgreen}{\eye} #4%
+}
+
+
+\begin{syntax}
+
+\begin{indexitemprocessinstruction}[form=\_,index key=_]{noop}([$n$]){no-op}
+ {&\meta{arg}&\meta{arg}&}[\_]
+
+ The argument is not processed, but simply skipped over. In other words, this instruction only
+ moves the head one item to the right. (This is like |expl3|'s argument specifier |n|.)
+
+ $n$ means repetition.
+
+ When the end of the instructions is reached, any remaining arguments on the right are processed
+ using this no-op instruction.
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{o}([$n$]){expand \emph{o}nce}
+ {&\meta{arg}&\meta{result}&}
+
+ \meta{arg} is expanded once. (This is like |expl3|'s argument specifier |o|).
+
+ The operation is repeated $n$ times (default, one) without moving the head between the
+ repetition. For example, |o3| expands the argument three times (and then moves the head right).
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{x}{fully e\emph{x}pand}
+ {&\meta{arg}&\meta{result}&}
+
+ \meta{arg} is fully expanded using |\edef|. (This is like |expl3|'s argument specifier |x|.)
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{O}([$n$]){\emph{o}ption}
+ {&\meta{option}&\meta{result}&}
+
+ \meta{option}=\alternative{\meta{option name},\meta{relative node name}\texttt{.}\meta{option name}}
+
+ In the former case, \meta{result} is the value of option at the current node, in the latter, the
+ value of option at the node referred to by \meta{relative node name}.
+
+ $n$ means repetition.
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{R}([$n$]){\emph{r}egister}
+ {&\meta{register}&\meta{result}&}
+
+ \meta{result} is the value of register \meta{register}.
+
+ $n$ means repetition.
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{P}([$n$]){\emph{p}gfmath}
+ {&\meta{pgfmath expr}&\meta{result}&}
+
+ \meta{result} is the result of evaluating \meta{pgfmath expr} using |\pgfmathparse|.
+
+ $n$ means repetition.
+
+ Combining \index{processor>P} and \index{processor>w}, \index{handler>process} is capable of anything
+ \index{wrap $n$ pgfmath args} can do. Even better, as we can combine pgfmath and non-pgfmath
+ methods, computations that use \index{handler>process} can be (much!) faster. Study the following
+ examples to see how less and less pgfmath is used to achieve the same result --- but note that
+ such extreme antipgfmathism probably only makes sense for style/package developers in computations
+ that get performed many times.
+
+\begin{forestexample}[index={handler>process,processor>w,processor>O,processor>W,processor>P,processor>+}]
+ \begin{forest}
+ [,grow'=east, where level=1{}{phantom,ignore,ignore edge}
+ [(a),delay={content/.wrap 4 pgfmath args={#1 $#2*#3=#4$}
+ {content}{content("!1")}{content("!2")}{int(content("!1")*content("!2"))}}
+ [6][7]]
+ [(b),delay={content/.process={O OO~P~ w4}
+ {content}
+ {!1.content}{!2.content}{int(content("!1")*content("!2"))}
+ {#1 $#2*#3=#4$}}
+ [6][7]]
+ [(c),delay={content/.process={O OO ~W2+P~ w4}
+ {content}
+ {!1.content}{!2.content}{int(#1*#2)}
+ {#1 $#2*#3=#4$}}
+ [6][7]]
+ [(d),delay={content/.process={O OO ~W2+n~ w4}
+ {content}
+ {!1.content}{!2.content}{#1*#2}
+ {#1 $#2*#3=#4$}}
+ [6][7]]
+ ]
+ \end{forest}
+\end{forestexample}
+
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{n}([$n$]){\emph{n}umexpr}
+ {&\meta{numexpr}&\meta{result}&}
+
+ \meta{result} is the result of evaluating \meta{dimexpr} using e\TeX's |\number\numexpr|.
+
+ $n$ means repetition.
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{d}([$n$]){\emph{d}imexpr}
+ {&\meta{dimexpr}&\meta{result}&}
+
+ \meta{result} is the result of evaluating \meta{dimexpr} using e\TeX's |\the\dimexpr|.
+
+ $n$ means repetition.
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{+}([$n$]){chain instructions}
+ {\meta{arg}&&&\meta{arg}}
+
+ This action allows one to ``process the same argument more than once''. It does not process the
+ current argument (in fact, there need not be any current argument), but rather moves the last
+ result back in the argument queue. In other words, our machine's head moves one step left. You
+ can also imagine it as an inverse of \index{processor>noop}.
+
+ $n$ means repetition.
+
+\end{indexitemprocessinstruction}
+
+\begin{forestexample}[index={handler>process,processor>O,processor>noop}]
\begin{forest}
- [
- {1,2,3,4,5},
- delay={
- my append/.style={if={strequal("#1","")}{}{append={[#1]}}},
- split/.~process args~={O+r}{content}{,}{my append},
- }
- ]
+ test/.style n args={3}{align=center,
+ content={The value of my option \texttt{#1} is \texttt{#2}.\\#3}}
+ [~fit~,delay={test/.process={O ~O+O~}{content}~{content}~{Yes it is!}}]
\end{forest}
\end{forestexample}
+
+\begin{indexitemprocessinstruction}{w}([$n$]){(consuming) \emph{w}rap}
+ {\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&\meta{macro body}&\meta{result}&}
+\end{indexitemprocessinstruction}
+\itemnosep[2pt]
+\begin{indexitemprocessinstruction}{W}([$n$]){(non-consuming) \emph{w}rap}
+ {\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&\meta{macro body}&
+ \meta{arg$_{1}$}\dots\meta{arg$_{n}$}\meta{result}&}
+
+ Defines a temporary macro with $n$ undelimited arguments using the \meta{macro body} given on the
+ right and expands it (once). The arguments given to the temporary macro are taken from the left:
+ \meta{arg$_{1}$}\dots\meta{arg$_{n}$}. The result of the expansion is stored as \meta{result} to
+ the right.
+
+ With |w|, \meta{arg$_{1}$}\dots\meta{arg$_{n}$} are ``consumed'', i.e.\ they are removed from the
+ result list on the left. |W| keeps \meta{arg$_{1}$}\dots\meta{arg$_{n}$} in the result list.
+
+ Default $n$ is 1. (Specifying $n>9$ raises an error.)
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}[form={\&},index key=\&]{and}([$n$]){boolean ``and''}*{}
+\end{indexitemprocessinstruction}
+\itemnosep[2pt]
+\begin{indexitemprocessinstruction}[form={\protect\indexpipe},index key=\&or]{or}([$n$]){boolean ``or''}
+ {\meta{arg$_{1}$}\meta{arg$_{2}$}&&\meta{result}&}
+
+ \meta{result} is a boolean conjunction/disjunction of $n$ arguments. The arguments are taken from
+ the left. They should be numbers (positive integers): |0| means false, any other number means
+ true. The \meta{result} is always |0| or |1|.
+
+ Default $n$ is 2.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}[form={!},index key=!]{not}{boolean ``not''}
+ {\meta{arg}&&\meta{result}&}
+
+ \meta{result} is a boolean negation of the argument. The argument is taken from the left. It
+ should be a number (positive integer): |0| means false, any other number means true. The
+ \meta{result} is always |0| or |1|.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{?}{conditional (if \dots\ then\dots\ else)}
+ {\meta{condition}&\meta{true arg}\meta{false arg}&&\meta{result}}
+
+ \meta{result} is \meta{true arg} is \meta{condition} is true (non-zero), otherwise \meta{false
+ arg}.
+
+ The condition is taken from the left. The true and false arguments are expected on the right,
+ where the winner is left as well.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}[form={=},index key={=}]{equal}{comparison: $\meta{arg$_{1}$}=\meta{arg$_{2}$}$?}*{}
+\end{indexitemprocessinstruction}
+\itemnosep[1pt]
+\begin{indexitemprocessinstruction}[form={<},index key={<}]{lt}{comparison: $\meta{arg$_{1}$}<\meta{arg$_{2}$}$?}*{}
+\end{indexitemprocessinstruction}
+\itemnosep[1pt]
+\begin{indexitemprocessinstruction}[form={\protect\greaterthan},index key={<<}]{gt}{comparison: $\meta{arg$_{1}$}>\meta{arg$_{2}$}$?}
+ {\meta{arg$_{1}$}\meta{arg$_{2}$}&&\meta{result}&}
+
+ Compare \meta{arg$_{1}$} and \meta{arg$_{2}$}, returning |1| (true) if \meta{arg$_{1}$} is equal
+ to / less than / greater than \meta{arg$_{2}$}, |0| (false) otherwise.
+
+ The arguments are taken from the left. They can be either numbers, dimensions, text or token
+ lists. Both arguments are expected to be of the same type. The type of comparison is determined
+ by the type of the result returned by the last instruction.
+ \index{processor>O}/\index{processor>R} look up the type of option/register to determine the type
+ (booleans are numbers and keylists are toks). Text type must be marked explicitely using
+ \index{processor>t}.
+
+ Comparison is carried out using |\ifnum| for numbers, |\ifdim| for dimensions (this includes
+ unitless decimals returned by pgfmath) and |\pdfstrcmp|\footnote{\texttt{\string\pdfstrcmp}
+ expands its arguments.} for text --- for these three types, all three comparison operators are
+ supported. For generic token lists, only |=| makes sense and is carried out using |\ifx|.
+
+ In the following example, (a) performs lexicographical comparison because we have marked |21| as
+ text; (b) and (c) perform numeric comparison: in (b), the type is automatically determined from
+ the type of register \indexex{tempcounta}, in (c) |21| is marked manually using \index{processor>n}.
+
+\begin{forestexample}[index={if,processor>gt,processor>lt}]
+ \forestset{
+ tempcounta=100,
+ TeX/.process={Rw1}{tempcounta}{$#1>21$?\ },
+ TeX={(a)\ }, if={>{Rt>}{tempcounta}{21}}{TeX=yes}{TeX=no},TeX={,\ },
+ TeX={(b)\ }, if={>{_R<}{21}{tempcounta}}{TeX=yes}{TeX=no},TeX={,\ },
+ TeX={(c)\ }, if={>{Rn>}{tempcounta}{21}}{TeX=yes}{TeX=no},
+ }
+\end{forestexample}
+
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{t}{mark as \emph{t}ext}
+ {&\meta{arg}&\meta{arg}&}
+
+ The result is not changed, only its type is changed to text. This is relevant only for
+ comparisons --- both argument processor's comparisons \index{processor>equal}, \index{processor>gt}
+ and \index{processor>lt} and sort keys (see \index{sort by}).
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{c}{to lowercase}
+ {&\meta{arg}&\meta{result}&}
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{C}{to uppercase}
+ {&\meta{arg}&\meta{result}&}
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{-}{toggle ascending/descending order (negate)}
+ {\meta{arg}&&\meta{result}&}
+
+ If the argument is of the text type, its sorting order is changed from ascending to descending or
+ vice versa.
+
+ For any numerical argument type (number, dimension, unitless dimension), the argument is actually
+ negated, which obviously has the same effect on sorting.
+
+ For generic type arguments, this operation is a no-op.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{u}{\emph{u}ngroup}
+ {&\meta{arg}&&\meta{item$_1$}\dots\meta{item$_n$}}
+
+ As every \TeX\ undelimited macro argument, \meta{arg} is a list of tokens or braced token lists.
+ This instruction puts those items back to the right as ``separate arguments''.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{s}([$n$]){(consuming) \emph{s}ave}
+ {\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&&&}
+\end{indexitemprocessinstruction}
+\itemnosep[2pt]
+\begin{indexitemprocessinstruction}{S}([$n$]){(non-consuming) \emph{s}ave}
+ {\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&&\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&}
+
+ Saves the last $n$ arguments from the left into a ``special place''.
+
+ With |s|, \meta{arg$_{1}$}\dots\meta{arg$_{n}$} are ``consumed'', i.e.\ they are removed from the
+ result list on the left. |S| keeps \meta{arg$_{1}$}\dots\meta{arg$_{n}$} in the result list.
+
+ Default $n$ is 1.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{l}([$n$]){(consuming) \emph{l}oad}
+ {&&\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&}
+\end{indexitemprocessinstruction}
+\itemnosep[2pt]
+\begin{indexitemprocessinstruction}{L}([$n$]){(non-consuming) \emph{l}oad}
+ {&&\meta{arg$_{1}$}\dots\meta{arg$_{n}$}&}
+
+ Loads $n$ arguments from the ``special place'' to the left.
+
+ With |l|, \meta{arg$_{1}$}\dots\meta{arg$_{n}$} are ``consumed'', i.e.\ they are removed from the
+ special place. |S| keeps \meta{arg$_{1}$}\dots\meta{arg$_{n}$} in the special place.
+
+ The default $n$ is 0 and indicates that the entire special place should be loaded.
+\end{indexitemprocessinstruction}
+
+\begin{indexitemprocessinstruction}{r}{\emph{r}everse (key)list}
+ {&\meta{list}&\meta{result}&}
+
+ \meta{list} should be a comma-separated list (\emph{not} a name of a keylist option or register).
+ \meta{result} contains the same elements in the reverse order.
+\end{indexitemprocessinstruction}
+
\end{syntax}
-\subsubsection{Aggregate functions}
+
+
+
+
+\subsection{Aggregate functions}
\label{ref:aggregate-functions}
-Aggregate functions are defined as handlers over options. They walk a nodewalk, use the values of visited options to calculate something, and store the result in the handled option.
+Aggregate functions walk a nodewalk and use the information found in the visited nodes to calculate
+something.
-Aggregate functions cannot be nested.
+All aggregate functions are available both as key handlers and |pgfmath| functions.
+
+
\begin{syntax}
- \indexitem{aggregate>count}|=|\meta{nodewalk}
+ \indexitem{aggregate>count}|=|\meta{nodewalk},
+ \indexdef[form={aggregate_count}]{pgfmath>aggregate count}|("|\meta{nodewalk}|")|
Store the number of nodes visited in the nodewalk into the handled option.
-\indexitem{aggregate>sum}|=|\meta{pgfmath}\meta{nodewalk}\itemnosep
-\indexitem{aggregate>average}|=|\meta{pgfmath}\meta{nodewalk}\itemnosep
-\indexitem{aggregate>product}|=|\meta{pgfmath}\meta{nodewalk}\itemnosep
-\indexitem{aggregate>min}|=|\meta{pgfmath}\meta{nodewalk}\itemnosep
-\indexitem{aggregate>max}|=|\meta{pgfmath}\meta{nodewalk}
+\indexitem{aggregate>sum}|=|\index{forestmath}\meta{nodewalk},
+\indexdef[form={aggregate_sum}]{pgfmath>aggregate sum}|("|\index{forestmath}|","|\meta{nodewalk}|")|
+\itemnosep
- Calculate the value of \meta{pgfmath} expression at each visited node. Store the sum / average / product / minimum / maximum of these values into the handled option.
+\indexitem{aggregate>average}|=|\index{forestmath}\meta{nodewalk},
+\indexdef[form={aggregate_average}]{pgfmath>aggregate average}|("|\index{forestmath}|","|\meta{nodewalk}|")|
+\itemnosep
-\indexitem{aggregate>aggregate}|=|\meta{pgfmath: start value}\meta{pgfmath: every step}\meta{pgfmath: after walk}\meta{nodewalk}
+\indexitem{aggregate>product}|=|\index{forestmath}\meta{nodewalk},
+\indexdef[form={aggregate_product}]{pgfmath>aggregate product}|("|\index{forestmath}|","|\meta{nodewalk}|")|
+\itemnosep
- The generic aggregate function. First, the result is set to \meta{pgfmath: start value}. Then,
- the given nodewalk is walked. After each step of the \meta{nodewalk}, \meta{pgfmath: every step} expression is evaluated in the context of the new current node and stored as the result. After the walk, the current node is reset to the origin. \meta{pgfmath: after walk} expression is then evaluated in its context and stored as the result.
+\indexitem{aggregate>min}|=|\index{forestmath}\meta{nodewalk},
+\indexdef[form={aggregate_min}]{pgfmath>aggregate min}|("|\index{forestmath}|","|\meta{nodewalk}|")|
+\itemnosep
- Use (appropriately escaped) |#1| to refer to the current value of the result in \meta{pgfmath:
- every step} and \meta{pgfmath: after walk}. Use count register \index{aggregate n} to refer
- to the current step number (in \meta{pgfmath: every step}) or the total number of steps (in \meta{pgfmath: after walk})
+\indexitem{aggregate>max}|=|\index{forestmath}\meta{nodewalk},
+\indexdef[form={aggregate_max}]{pgfmath>aggregate max}|("|\index{forestmath}|","|\meta{nodewalk}|")|
- Example 1: see \index{option>s}.
+Calculate the value of the given \index{forestmath} expression at each visited node. Store the sum /
+average / product / minimum / maximum of these values into the handled option (handlers) or return
+it (pgfmath functions).
- Example 2: the definition of \index{aggregate>average} below. Note that as we are using
- |.aggregate| inside a style definition, |##1| must be used to refer to the current value of the
- result.
-\begin{lstlisting}[]
- /handlers/~.average~/.style 2 args={
- /handlers/~.aggregate~=
- {0}
- {(##1)+(#1)}
- {##1/\forestregister{aggregate n}}
- {#2}
- }
-\end{lstlisting}
- Example 3: randomly generate the content of leaves; the content of a parent is the sum of it's children's content.
+\indexitem{aggregate>aggregate}|=|\index{forestmath=start value}\index{forestmath=every
+ step}\index{forestmath=after walk}\meta{nodewalk}
+\itemnosep
+\indexitem{pgfmath>aggregate}|("|\index{forestmath=start value}|","|\index{forestmath=every step}|","|\index{forestmath=after walk}|","|\meta{nodewalk}|")|
+
+The generic aggregate function. First, register \index{aggregate result} is set to
+\index{forestmath=start value}. Then, the given nodewalk is walked. After each step of the
+\meta{nodewalk}, \index{forestmath=every step} expression is evaluated in the context of the new
+current node and stored into \index{aggregate result}. After the walk, the current node is reset to
+the origin. \index{forestmath=after walk} expression is then evaluated in its context and stored
+into \index{aggregate result} as the final result.
+
+Use \index{aggregate result} and \index{aggregate n} in the \index{forestmath} expressions to refer to
+the current result value and step number.
+
+\indexitem{register>aggregate n}|=|\meta{count} the current step number
+
+In the every-step expression of an aggregate function, refers to the (real) step number in the
+aggregate's \meta{nodewalk}. In the after-walk expression, refers to the total number of (real)
+steps made.
+
+\indexitem{register>aggregate result}|=|\meta{toks} the current value of the result
+
+ This register is where the intermediate results are stored.
+
+\indexitem{register>aggregate value}|=|\meta{toks} the value of the expression at the current node
+
+This only applies to special aggregates like \index{aggregate>sum}, not to the generic
+\index{aggregate>aggregate}.
+\indexitem{node key>aggregate postparse}|=|\alternative{none,int,print,macro}
+
+Roughly speaking, how should the result be formatted? For details, see \citep[\S89]{tikzpgf3.0.0}.
+Applies only to |pgfmath| versions of aggregate functions, i.e.\ not to the |'| variants.
+
+ \begin{syntax}
+ \item\indexdef{value of=aggregate postparse>none}
+ No formatting.
+ \item\indexdef{value of=aggregate postparse>int}
+ The result is an integer.
+ \item\indexdef{value of=aggregate postparse>print}
+ Use |pgf|'s number printing extension, see \citep[\S93]{tikzpgf3.0.0}.
+ \item\indexdef{value of=aggregate postparse>macro}
+ Use a custom macro. Specify the macro using \indexdef{node key>aggregate postparse macro}|=|\meta{cs}.
+ \end{syntax}
+
+\end{syntax}
+
+Example 1. Randomly generate the content of leaves. The content of a parent is the sum of its
+children's content. Note how we use \indexex{tree children-first} to proceed in a bottom-up
+fashion.
+
\begin{forestexample}[index={delay,aggregate postparse,for step,tree children-first,if option,n children,content,pgfmath,sum,step>children}]
\begin{forest}
delay={
@@ -4843,27 +5770,35 @@
[[[[][]][]][[][][[][][]]][[][[][]]]]
\end{forest}
\end{forestexample}
-
-\indexitem{register>aggregate n}|=|\meta{count}
- In the every-step expression of an aggregate function, refers to the (real) step number in the aggregate's \meta{nodewalk}. In the after-walk expression, refers to the total number of (real) steps made.
-\indexitem{node key>aggregate postparse}|=|\alternative{none,int,print,macro}
+ Example 2: nested aggregate functions. We are given the black numbers. The inner aggregate, the
+ sum of children, is applied at every blue node. (See how we actually display the blue numbers by
+ storing \index{aggregate value} to \index{content}.) The outer aggregate stores the maximum blue
+ number into the red root.
- Roughly speaking, how should the result be formatted? For details, see \citep[\S89]{tikzpgf3.0.0}.
+\begin{forestexample}
+ \begin{forest}
+ delay={
+ aggregate postparse=int,
+ content/~.max~=%
+ {~aggregate_sum~("content","children")}%
+ {every step={content/.register=~aggregate value~},children}%
+ } [ [[1][2][3]] [[3][4][5]] [[2][3][4]] ]
+ \end{forest}
+\end{forestexample}
- \begin{syntax}
- \item\indexdef{value=aggregate postparse>none}
- No formatting.
- \item\indexdef{value=aggregate postparse>int}
- The result is an integer.
- \item\indexdef{value=aggregate postparse>print}
- Use |pgf|'s number printing extension, see \citep[\S93]{tikzpgf3.0.0}.
- \item\indexdef{value=aggregate postparse>macro}
- Use a custom macro. Specify the macro using \indexdef{node key>aggregate postparse macro}|=|\meta{cs}.
- \end{syntax}
-
-\end{syntax}
+Example 3: calculate root mean square of children using the generic \index{aggregate>aggregate} handler.
+\begin{forestexample}
+ \begin{forest}
+ delay={
+ content/~.aggregate~=
+ {0}{~aggregate_result~()+content()^2}{sqrt(~aggregate_result~/~aggregate_n~)}
+ {children}
+ }
+ [[0][1][2][3][4]]
+ \end{forest}
+\end{forestexample}
\subsection{Relative node names}
\label{ref:relative-node-names}
@@ -4902,9 +5837,9 @@
is a keylist; the following keys are accepted.
\begin{syntax}
-\indexitem{forest cs>name}|=|\meta{node name} The node with the given name becomed the current node. The
+\indexitem{forest cs>name}|=|\meta{node name} The node with the given name becomes the current node. The
resulting point is its (node) anchor.
-\indexitem{forest cs>id}|=|\meta{node id} The node with the given name becomed the current node. The
+\indexitem{forest cs>id}|=|\meta{node id} The node with the given name becomes the current node. The
resulting point is its (node) anchor.
\indexitem{forest cs>go}|=|\meta{nodewalk} Walk the given nodewalk, starting at the current node. The
node at the end of the walk becomes the current node. The resulting point is its (node) anchor.
@@ -4930,6 +5865,7 @@
\FoRest; defines several anchors which can be used with any \TikZ; node belonging to a \FoRest;
tree (manually added \TikZ; nodes are thus excluded).
+\newcommand\indexdefneganchor[1]{\indexdef[index key=#1]{anchor>-#1}}
\begin{syntax}
\indexitem{anchor>parent anchor}\itemnosep
\indexitem{anchor>child anchor}\itemnosep
@@ -4938,21 +5874,23 @@
These anchors point to coordinates determined by node options \index{option>parent anchor},
\index{option>child anchor} and \index{option>anchor}.
-\indexitem{anchor>parent}, \indexdef{anchor>parent'}\itemnosep
-\indexitem{anchor>parent first}, \indexdef{anchor>parent first'}\itemnosep
+\indexitem{anchor>parent}, \indexdef{anchor>parent'}, \indexdefneganchor{parent}, \indexdefneganchor{parent'}\itemnosep
+\indexitem{anchor>parent first}, \indexdef{anchor>parent first'}, \indexdefneganchor{parent first}, \indexdefneganchor{parent first'}\itemnosep
\indexitem{anchor>first}, \indexdef{anchor>first'}\itemnosep
-\indexitem{anchor>children first}, \indexdef{anchor>children first'}\itemnosep
-\indexitem{anchor>children}, \indexdef{anchor>children}\itemnosep
-\indexitem{anchor>children last}, \indexdef{anchor>children last}\itemnosep
-\indexitem{anchor>last}, \indexdef{anchor>last}\itemnosep
-\indexitem{anchor>parent last}, \indexdef{anchor>parent last}
+\indexitem{anchor>children first}, \indexdef{anchor>children first'}, \indexdefneganchor{children first}, \indexdefneganchor{children first'}\itemnosep
+\indexitem{anchor>children}, \indexdef{anchor>children'}, \indexdefneganchor{children}, \indexdefneganchor{children'}\itemnosep
+\indexitem{anchor>children last}, \indexdef{anchor>children last'}, \indexdefneganchor{children last}, \indexdefneganchor{children last'}\itemnosep
+\indexitem{anchor>last}, \indexdef{anchor>last'}\itemnosep
+\indexitem{anchor>parent last}, \indexdef{anchor>parent}, \indexdefneganchor{parent last},\indexdefneganchor{parent last'}
+
Growth direction based anchors.
\TikZ;'s ``compass anchors'' |east|, |north| etc.\ resolve to coordinates on the border of the
node facing east, north etc.\ (for the shapes that define these anchors). The above \FoRest;'s
anchors are similar in that they also resolve to coordinates on the border of the node. However,
- the ``cardinal directions'' are determined by the \index{grow}th direction of the tree in the node, so
- that
+ the ``cardinal directions'' are determined by the \index{grow}th direction of the tree in the node
+ and its parent:
+
\begin{itemize}
\item anchor |parent| faces the parent node (or, in case of the root, where the parent would be);
\item anchor |children| faces the children (or, in case of a node without children, where the children would be);
@@ -4959,18 +5897,60 @@
\item anchor |first| faces the first child (or \dots\ you get it, right?);
\item anchor |last| faces the last child (or \dots\ you know!).
\end{itemize}
- Combinations like |parent_children| work like combinations of compass directions, e.g.\
- |north_west|. These anchors work as expected even if the node is \index{rotate}d, or if the
- children are \index{reversed}.
+ Combinations like |children_first| work like combinations of compass directions, e.g.\
+ |north_west|, but note that
+ \begin{itemize}
+ \item when |first| and |last| are combined with |parent| into |parent_first| and |parent_last|,
+ they refer to the first and last child of the parent node, i.e.\ siblings of the current node.
+ \end{itemize}
+ While |first| and |last| always point in opposite directions, |parent| and |children| do not do so
+ if the \index{grow}th direction of the tree changes in the node, i.e.\ if the node's \index{grow}
+ differs from it's parent's \index{grow}. Thus in general, it is useful to have anchors |-parent|
+ and |-children|, which point in the opposite directions as |parent| and |children|, respectively,
+ and their combinations with |first| and |last|.
+
The |'| variants refer precisely to
the point where the cardinal growth direction intersects the border. Variants without |'| snap to
the closest compass anchor of the node.
-
+
+ These anchors work as expected even if the node is \index{rotate}d, or if the
+ children are \index{reversed}.
+
For simple examples, see definitions of \index{sn edges} and \index{roof}; for more involved
examples, see the \reflibrary{edges} library.
\end{syntax}
+\begin{forestexample}[layout=tree on top]
+ \def\redorblue#1{\expandafter\redorbluei#1\END}%
+ \def\redorbluei#1#2\END{\expandafter\ifx#1-red\else blue\fi}%
+ \forestset{
+ draw anchors/.style n args=3{% #1=above, #2=below, #3='-variant of anchor?
+ tikz={
+ \foreach \a in {first,last,parent first,parent last,children,children last,#1}
+ {\fill[](.\a#3)circle[radius=1pt] node[above,font=\tiny,color=\redorblue\a]{\a#3};}
+ \foreach \a in {-parent first,-parent,-parent last,-children,-children first,#2}
+ {\fill[](.\a#3)circle[radius=1pt] node[below,font=\tiny,color=\redorblue\a]{\a#3};}
+ }
+ },
+ draw anchors/.default={parent,children first}{-children last}{},
+ }
+ \begin{forest}
+ for tree={
+ minimum width=10em, minimum height=13ex, s sep+=5em,
+ draw, draw anchors,
+ font=\tt, delay={content/.process=OOw2{grow}{reversed}{grow\ifnum#2=1'\fi=#1}}
+ }
+ [
+ [,rotate=20,draw anchors={parent,children first}{-children last}{'}]
+ [,for tree={grow'=0}, l sep+=5em, draw anchors={-children last}{parent,children first}{}
+ [,rotate=-60]
+ []
+ ]
+ ]
+ \end{forest}
+\end{forestexample}
+
\subsection{Additional \texttt{pgfmath} functions}
\label{ref:pgfmath}
@@ -5016,10 +5996,10 @@
Boolean function \indexdef{pgfmath>valid} returns true if the node's \index{readonly option>id}$\neq0$, i.e.\ if the node is a real, valid node; see \S\ref{ref:spatial-propagators} and \S\ref{ref:nodewalks}. Boolean function \indexdef{pgfmath>invalid} is a negation of |valid|.
\begin{syntax}
-\indexitem[set={+format={detokenize}}]{pgfmath>min_l}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)| \itemnosep
-\indexitem[set={+format={detokenize}}]{pgfmath>min_s}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)| \itemnosep
-\indexitem[set={+format={detokenize}}]{pgfmath>max_l}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)| \itemnosep
-\indexitem[set={+format={detokenize}}]{pgfmath>max_s}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)|
+\indexitem{pgfmath>min_l}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)| \itemnosep
+\indexitem{pgfmath>min_s}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)| \itemnosep
+\indexitem{pgfmath>max_l}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)| \itemnosep
+\indexitem{pgfmath>max_s}|=(|\meta{nodewalk: node}|,|\meta{nodewalk: context node}|)|
These functions return the minimum/maximum value of \index{option>l}/\index{option>s} of node at the end of \meta{nodewalk:
node} in the context (i.e.\ growth direction) of node at the end of \meta{nodewalk: context
@@ -5070,18 +6050,18 @@
\end{forest}
\end{forestexample}
+{\def\useforestlibrary#1{}%
\begin{forestexample}[point=instr,index={where option,n children,tier,content,no edge,tikz},index>={!}]
% roof terminal phrases
+ \useforestlibrary{linguistics}
+ % ...
\begin{forest}
- where n children=0{tier=word,
- if={~instr~("P",~content~("!u"))}{no edge,
- tikz={\draw (!.north west)--
- (!.north east)--(!u.south)--cycle;
- }}{}
- }{},
+ delay={where n children=0{tier=word,
+ if={~instr~("P",~content~("!u"))}{roof}{}
+ }{}},
[VP[DP[Mary]][V'[V[loves]][DP[her cat]]]]
\end{forest}
-\end{forestexample}
+\end{forestexample}}
\subsection{Standard node}
@@ -5262,13 +6242,89 @@
\subsection{Changelog}
\label{sec:changelog}
-First of all, the list of all \index{compat} keys for backward compatibility, and their groupings.
+First of all, the list of all \index{compat} key values for backward compatibility, and their
+groupings. Remember, compat values that reside in styles with suffix |-most| are harmless: they will
+not disrupt the new functionality of the package. But take care when using stuff which only resides
+in |-all| styles.
\lstinputregion{forest-compat.sty}{compat_keys}
+\newcommand\compatitem[2]{\item[,,in \texttt{-#1}]\texttt{compat=}\indexdef{value of=compat>#2}}
+
+\subsubsection{v2.1}
+
+\begin{description}
+\item[v2.1 (2016/12/05)] \mbox{}
+
+ Backward incompatible changes (with a \index{compat} key):
+ \begin{syntax}
+ \compatitem{all}{2.0-edges}
+ This compat key groups the three changes listed below: the final two depend on the first, so you
+ will probably want to revert them all or none.
+ \begin{syntax}
+ \compatitem{all}{2.0-anchors}
+ This is really a bugfix. Growth direction based anchors \index{anchor>parent},
+ \index{anchor>parent first} and \index{anchor>parent last} were not facing to the direction of the
+ parent if the growth direction of the tree changed at the node.
+ \compatitem{all}{2.0-forkededge}
+ \compatitem{all}{2.0-folder}
+ Update the code of keys \index{forked edge} (and friends) and \index{folder} from the
+ \reflibrary{edges} library to reflect the above bugfix.
+ \end{syntax}
+ \compatitem{all}{2.0-delayn} Fixing yet another bug in \index{delay n}! The number of cycles was
+ reevaluated at each cycle. Now it is computed immediately, and fixed. Use this key to revert to
+ the old behaviour.
+ \end{syntax}
+
+ Performance:
+ \begin{itemize}
+ \item Substantially enhance the argument processor (\S\ref{ref:argument-processor}), including the
+ ability to use it as a drop-in replacement for |pgfmath|.
+ \item Internally, avoid using |\pgfmathparse| and friends whereever possible.
+ \item Implement a fast set of macros to determine if a |pgfmath| expression is just a \meta{count}
+ or \meta{dimen} expression.
+ \item Optimize \index{split option} and \index{split register}.
+ \end{itemize}
+ Minor improvements:
+ \begin{itemize}
+ \item Allow \index{relative node name}s in \index{handler>option}.
+ \item Make aggregate functions (\S\ref{ref:aggregate-functions}) nestable and implement their
+ |pgfmath| versions.
+ \item Implement
+ \index{if dimen GT=\meta{dimen option}}, \index{if dimen LT=\meta{dimen option}},
+ \index{if count GT=\meta{count option}}, \index{if count LT=\meta{count option}},
+ \index{where dimen GT=\meta{dimen option}}, \index{where dimen LT=\meta{dimen option}},
+ \index{where count GT=\meta{count option}} and \index{where count LT=\meta{count option}},
+ \item Implement \index{if current nodewalk empty}.
+ \item Implement nodewalk steps \index{leaves}, \index{-level} and \index{-level'}.
+ \item Implement nodewalk operation \index{unique}.
+ \item Implement \index{nodewalk key>on invalid} values \index{value of=on invalid>error if real} and \index{value of=on invalid>last valid}, remove value |step| (no \index{compat} key, as it was broken and useless).
+ \item Implement `-` anchors (\index{anchor>-parent} etc.).
+ \item Implement \index{save and restore register}.
+ \item Implement \index{handler>nodewalk style}.
+ \item Implement \index{forestloopcount}.
+ \item Allow multiple occurrences of package option \index{compat}.
+ %\item Implement \index{foresttypeouttrees}.
+ %\item Implement \index{show register}.
+ \end{itemize}
+
+ Bugfixes:
+ \begin{itemize}
+ \item Fix a bug in externalization (|\forest at file@copy| set |\endlinechar| to |-1|, which caused
+ problems for several packages, e.g. |biblatex|).
+ \item Fix a bug in \index{delay n}: the number of cycles was reevaluated at each cycle.
+ \item Fix a bug in \index{fixed edge angles}.
+ \item Fix \index{compat} key values \index{value of=compat>silent}, \index{value of=compat>1.0-forstep} and \index{value of=compat>1.0-stages}.
+ \item Fix invocations of spatial propagators \index{for step=\index{step>nodewalk}} and \index{for step=\index{step>Nodewalk}} and \index{node key>Nodewalk}.
+ \item Fix invocations of \index{for step=group}, \index{for step=next on tier} and \index{for step=previous on tier}.
+ \item Fix behaviour of \index{for step=next on tier}, \index{for step=previous on tier} and \index{for step=to tier} on arrival to the invalid node.
+ \item Fix problems with interaction between \index{folder} and \index{forked edges}.
+ \end{itemize}
+
+\end{description}
+
\subsubsection{v2.0}
-\newcommand\compatitem[2]{\item[,,in \texttt{-#1}]\texttt{compat=}\indexdef{option of=compat>#2}}
\begin{description}
\item[v2.0.3 (2016/04/03)] \mbox{}
@@ -5276,7 +6332,6 @@
Backward incompatible changes (with a \index{compat} key):
\begin{syntax}
\compatitem{all}{2.0.2-delayn}
- \itemnosep
\compatitem{all}{2.0.2-wrapnpgfmathargs}
This is really a bugfix: keys \index{delay n} and \index{wrap $n$ pgfmath args} (for $n\geq 2$)
@@ -5411,15 +6466,15 @@
\begin{tabularx}{\linewidth}{lll}
old&new&\index{compat} key {\small (all but the last are in \texttt{-most})}\\\hline
- \keyname{node walk}&\index{for step=nodewalk}\footnote{Nodewalks are much improved in v2.0, so some syntax and keys are different than in v1.0!}&\indexdef{option of=compat>1.0-nodewalk}\\
- \keyname{for}&\index{for step=\index{group}}&\indexdef{option of=compat>1.0-for}\\
- \keyname{for all next}&\index{for step=\index{following siblings}}&\indexdef{option of=compat>1.0-forall}\\
- \keyname{for all previous}&\index{for step=\index{preceding siblings}}&\indexdef{option of=compat>1.0-forall}\\
- \keyname{for ancestors'}&\index{for step=\index{current and ancestors}}&\indexdef{option of=compat>1.0-ancestors}\\
- (\keyname{for}) \keyname{linear next}&(\index{for step}) \index{next node}&\indexdef{option of=compat>1.0-linear}\\
- (\keyname{for}) \keyname{linear previous}&(\index{for step}) \index{previous node}&\indexdef{option of=compat>1.0-linear}\\
- \keyname{triangle}&\index{roof} (library \reflibrary{linguistics})&\indexdef{option of=compat>1.0-triangle}\\
- \keyname{/tikz/fit to tree}&\index{fit to}\keyname{=}\index{tree}\footnote{The v1.0 key \keyname{/tikz/fit to tree} also set \keyname{inner sep=0}; the v2.0 key \index{fit to} does not do that.}&\indexdef{option of=compat>1.0-fittotree}\\
+ \keyname{node walk}&\index{for step=nodewalk}\footnote{Nodewalks are much improved in v2.0, so some syntax and keys are different than in v1.0!}&\indexdef{value of=compat>1.0-nodewalk}\\
+ \keyname{for}&\index{for step=\index{group}}&\indexdef{value of=compat>1.0-for}\\
+ \keyname{for all next}&\index{for step=\index{following siblings}}&\indexdef{value of=compat>1.0-forall}\\
+ \keyname{for all previous}&\index{for step=\index{preceding siblings}}&\indexdef{value of=compat>1.0-forall}\\
+ \keyname{for ancestors'}&\index{for step=\index{current and ancestors}}&\indexdef{value of=compat>1.0-ancestors}\\
+ (\keyname{for}) \keyname{linear next}&(\index{for step}) \index{next node}&\indexdef{value of=compat>1.0-linear}\\
+ (\keyname{for}) \keyname{linear previous}&(\index{for step}) \index{previous node}&\indexdef{value of=compat>1.0-linear}\\
+ \keyname{triangle}&\index{roof} (library \reflibrary{linguistics})&\indexdef{value of=compat>1.0-triangle}\\
+ \keyname{/tikz/fit to tree}&\index{fit to}\keyname{=}\index{tree}\footnote{The v1.0 key \keyname{/tikz/fit to tree} also set \keyname{inner sep=0}; the v2.0 key \index{fit to} does not do that.}&\indexdef{value of=compat>1.0-fittotree}\\
\keyname{begin forest}, \keyname{end forest}&none (use \index{style>stages})&\index{1.0-stages}\\
\keyname{end forest}, \keyname{end forest}&none (use \index{style>stages})&\index{1.0-stages}\\
\end{tabularx}
@@ -5543,18 +6598,7 @@
\end{description}
-\paragraph{Acknowledgements}
-This package has turned out to be much more successful and widespread than I could have ever
-imagined and I want to thank all the users for the trust. Many of you have also contributed to the
-package in some way: by providing comments and ideas, sending patches, reporting bugs and so on. To
-you, I'm doubly grateful! I will not even try to list you all here, as the list is getting too long
-for me to maintain, but I do want to mention one person, a member of the friendly community at the
-excellent and indispensable \href{http://tex.stackexchange.com}{\TeX\ -- \LaTeX\ Stack Exchange} and
-the author of the very first \foRest;-based package,
-\href{http://ctan.org/pkg/prooftrees}{Prooftrees}: without |cfr|'s uncountable questions, answers,
-bug reports and ideas, \foRest; would be a much poorer package indeed.
-
\subsection{Known bugs}
\label{sec:bugs}
@@ -5585,7 +6629,7 @@
In the following example, the R--B edge crosses the AAA node, although \index{ignore edge} is
set to the default |false|.
-\begin{forestexample}[index={calign,{value=calign>first},align,{value=align>center},base,{value=base>bottom}}]
+\begin{forestexample}[index={calign,{value of=calign>first},align,{value of=align>center},base,{value of=base>bottom}}]
\begin{forest}
calign=first
[R[AAAAAAAAAA\\AAAAAAAAAA\\AAAAAAAAAA,align=center,base=bottom][B]]
@@ -5595,7 +6639,7 @@
computed before child alignment (which is obviously the correct order in the general case), but
child alignment non-linearly influences the edges. Observe that the with a different value of
\index{calign}, the problem does not arise.
-\begin{forestexample}[index={calign,{value=calign>last},align,{value=align>center},base,{value=base>bottom}}]
+\begin{forestexample}[index={calign,{value of=calign>last},align,{value of=align>center},base,{value of=base>bottom}}]
\begin{forest}
calign=last
[R[AAAAAAAAAA\\AAAAAAAAAA\\AAAAAAAAAA,align=center,base=bottom][B]]
@@ -5636,6 +6680,20 @@
Again, I don't think anything sensible can be done about this, in general.
+\subsection{Acknowledgements}
+
+This package has turned out to be much more successful and widespread than I could have ever
+imagined and I want to thank all the users for the trust. Many of you have also contributed to the
+package in some way: by providing comments and ideas, sending patches, reporting bugs and so on. To
+you, I'm doubly grateful! I will not even try to list you all here, as the list is getting too long
+for me to maintain, but I do want to mention one person, a member of the friendly community at the
+excellent and indispensable \href{http://tex.stackexchange.com}{\TeX\ -- \LaTeX\ Stack Exchange} and
+the author of the very first \foRest;-based package,
+\href{http://ctan.org/pkg/prooftrees}{Prooftrees}: without |cfr|'s uncountable questions, answers,
+bug reports and ideas, \foRest; would be a much poorer package indeed.
+
+
+
\addcontentsline{toc}{section}{References}
\bibliography{tex}
\bibliographystyle{plain}
@@ -5645,8 +6703,14 @@
\addcontentsline{toc}{section}{\indexname}
\addtocontents{toc}{\protect\setbox0=\protect\vbox{\protect\iffalse}\protect\fi}
\PrintIndex
-\addtocontents{toc}{\protect\iffalse{\protect\fi}}
+%\addtocontents{toc}{\protect\iffalse{\protect\fi}}
+%http://tex.stackexchange.com/questions/10291/addtocontents-at-end-of-document-not-getting-written-to-toc-file
+\makeatletter
+\write\@auxout{\noexpand\@writefile{toc}{\noexpand\iffalse{\noexpand\fi}}}
+\makeatother
+
+
\end{document}
%%% Local Variables:
Modified: trunk/Master/texmf-dist/doc/latex/forest/forest.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/latex/forest/forest-index.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/forest/forest-index.dtx 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/source/latex/forest/forest-index.dtx 2016-12-06 00:28:11 UTC (rev 42640)
@@ -1,9 +1,9 @@
-% \CheckSum{561}
+% \CheckSum{756}
% \iffalse meta-comment
% forest-index.dtx
%% `forest-index' is an indexing system for the documentation of package `forest', using the package itself.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -150,11 +150,14 @@
{\let\forestindex at resolvekey\forestindex at resolvekey@long}
{\let\forestindex at resolvekey\forestindex at resolvekey@shortorlong}%
\forestindex at index{example}{#1}{#3}}
+% \DeclareDocumentCommand\indexitem{D(){} O{} t> m}{%
+% \IfBooleanTF{#3}
+% {\let\forestindex at resolvekey\forestindex at resolvekey@long}
+% {\let\forestindex at resolvekey\forestindex at resolvekey@shortorlong}%
+% \forestindex at index{definition}{default={#1},print format=item,#2}{#4}}
\DeclareDocumentCommand\indexitem{D(){} O{} t> m}{%
- \IfBooleanTF{#3}
- {\let\forestindex at resolvekey\forestindex at resolvekey@long}
- {\let\forestindex at resolvekey\forestindex at resolvekey@shortorlong}%
- \forestindex at index{definition}{default={#1},print format=item,#2}{#4}}
+ \let\forestindex at resolvekey\forestindex at resolvekey@long
+ \forestindex at index{definition}{default={#1},#2,print format+=item}{#4}}
\DeclareDocumentCommand\indexset{O{} t> m}{%
\IfBooleanTF{#2}
{\let\forestindex at resolvekey\forestindex at resolvekey@long}
@@ -181,9 +184,10 @@
% \begin{macrocode}
\def\forestindex at index#1#2#3{%
% \end{macrocode}
-% Partition the index keylist into single keys.
+% Partition the index keylist into single keys. And put it all in a group: the
+% persistent stuff is saved globally.
% \begin{macrocode}
- \forcsvlist{\forestindex at forkey{#1}{#2}}{#3}%
+ {\forcsvlist{\forestindex at forkey{#1}{#2}}{#3}}%
}
\def\forestindex at forkey#1#2#3{%
% \end{macrocode}
@@ -191,11 +195,23 @@
% \begin{macrocode}
\forestindex at resolvekey{#3}%
% \end{macrocode}
+% Manipulate arguments a bit, so that we can use our quick-and-dirty one-arg
+% memoization.
+% \begin{macrocode}
+ %\forestset{@index/.process={__o}{#1}{#2}{\forestindex at fullkey}}
+ \edef\forest at marshal{%
+ \noexpand\forestindex at index@{%
+ {\unexpanded{#1}}%
+ {\unexpanded{#2}}%
+ {\expandonce{\forestindex at fullkey}}%
+ }%
+ }\forest at marshal
+}
+% \end{macrocode}
% Call the central processing command, style |@index|. See how
-% \indexex{process args} is used to expand (once) the last argument.
+% \indexex{handler>process} is used to expand (once) the last argument.
% \begin{macrocode}
- \forestset{@index/.process args={__o}{#1}{#2}{\forestindex at fullkey}}%
-}
+\def\forestindex at index@#1{\forestset{@index/.process={__o}#1}}
\forestset{
% \end{macrocode}
% \subsubsection*{Declarations}
@@ -206,6 +222,7 @@
% \begin{macrocode}
declare boolean register=print,
declare boolean register=index,
+ declare boolean register=short, short,
% \end{macrocode}
% Options |name|, |content|, |key| and |argument| hold info about the
% current entry. We need to declare only the latter two, the former
@@ -307,11 +324,15 @@
if n=0{
content/.option=key,
}{
- content/.wrap 2 pgfmath args={##1>##2}{content("!parent")}{key},
+ content/.process={OOw2} {!parent.content} {key} {##1>##2},
}
}{},
for root'={
% \end{macrocode}
+% Don't memoize if the key is of an unknown category.
+% \begin{macrocode}
+ if strequal/.process={O}{!root.name}{@unknown}{TeX=\global\forest at memoizing@ok at false}{},
+% \end{macrocode}
% Option |print_form| is what will be typeset in the text. Option
% |index_key| is the key that will be used for sorting the
% index. Option |index_form| is what will be typeset in the index. All
@@ -325,7 +346,7 @@
index form/.option=key,
},
% \end{macrocode}
-% Below, \indexex{node key>on invalid} is set to \indexex{value=on invalid>fake} at four points.
+% Below, \indexex{node key>on invalid} is set to \indexex{value of=on invalid>fake} at four points.
% This is so we won't get in trouble when |\indexset|ting the
% categories: when the category formatting code will try to step into
% the child, it will fail as the child does not exist when |\indexset|
@@ -345,7 +366,7 @@
% Ancestors are walked in the \indexex{reverse} order (top down). At
% every node, the saved configuration is executed (if it exists).
% \begin{macrocode}
- for reverse={ancestors}{on invalid={fake}{@@index/\forestoption{name}/.try}},
+ for reverse={current and ancestors}{on invalid={fake}{@@index/\forestoption{name}/.try}},
% \end{macrocode}
% We don't execute the saved configuration for definitions, as
% definitions are where the configuration is set.
@@ -377,17 +398,14 @@
% \FoRest; points:
% \begin{enumerate*}[(i)]
% \item the generic conditional \indexex{if},
-% \item handler \index[print form=wrap 2 pgfmath args]{wrap $n$ pgfmath args},
-% \item long nodewalk in the relative node name, which is an argument
-% to a |pgfmath| option function, automatically created for the
-% |index at hypertarget| option declared in this package.
+% \item handler \index{handler>process},
% \end{enumerate*}
% \begin{macrocode}
- if={index()||print()}{
+ if index={
index at hypertarget/.expanded={.\forestoption{index key}},
for descendants={
- index at hypertarget/.wrap 2 pgfmath args={##1.##2}%
- {index at hypertarget("!parent")}{index_key},
+ index at hypertarget/.process= {OOw2}
+ {!parent.index at hypertarget} {index key} {##1.##2},
},
}{},
% \end{macrocode}
@@ -441,15 +459,15 @@
},
},
temptoksa={},
- result={},
+ result'={},
if n children=0{tempboola}{not tempboola},
where index form={}{}{
% \end{macrocode}
-% If the (outer) current node has no children, make it the hypertarget
-% that the definitions in text will point to.
+% Create the hypertarget that the definitions in text and other index entries
+% will point to.
% \begin{macrocode}
- if tempboola={temptoksd/.expanded={\noexpand\protect\noexpand\hypertarget{%
- \forestoption{index at hypertarget}}{}}}{temptoksd={}},
+ temptoksd/.expanded={\noexpand\protect\noexpand\hypertarget{%
+ \forestoption{index at hypertarget}}{}},
% \end{macrocode}
% Add the (inner) current node to the index entry of the (outer) current node.
% \begin{macrocode}
@@ -467,7 +485,7 @@
% Do the actual indexing.
% \begin{macrocode}
result+/.expanded={|indexpagenumber\forestregister{index entry type}},
- TeX/.expanded={\noexpand\forestindex at LaTeX@index{\forestregister{result}}},
+ TeX and memoize/.expanded={\noexpand\forestindex at LaTeX@index{\forestregister{result}}},
},
endgroup
}{},
@@ -486,7 +504,7 @@
% \end{macrocode}
% Typeset the entry in the text.
% \begin{macrocode}
- for first leaf'={TeX={\forestoption{print form}}},
+ for first leaf'={TeX and memoize/.expanded={\forestoption{print form}}},
endgroup,
}{},
}
@@ -519,8 +537,8 @@
name'/.option=key,
content={#1},
}{
- name'/.wrap 2 pgfmath args={##1>##2}{name("!parent")}{key},
- content/.wrap pgfmath arg={##1>#1}{content("!parent")},
+ name'/.process={OOw2} {!parent.name} {key} {##1>##2},
+ content/.process={Ow1} {!parent.content} {##1>#1},
},
}
},
@@ -549,31 +567,33 @@
% \end{macrocode}
% Don't save entries of unknown category.
% \begin{macrocode}
- if={strequal(name("!root"),"@unknown")}{}{
+ if strequal/.process={O}{!root.name}{@unknown}{}{
% \end{macrocode}
% Don't save if nothing is set.
% \begin{macrocode}
if set={}{}{
- TeX={%
- \immediate\write\forestindex at out{%
- \string\indexloadsettings{\forestoption{name}}{\forestregister{set}}%
+ TeX and memoize/.expanded={%
+ \noexpand\immediate\noexpand\write\noexpand\forestindex at out{%
+ \noexpand\string\noexpand\indexloadsettings\noexpand\unexpanded{{\forestoption{name}}{\forestregister{set}}}%
}%
},
},
+ },
% \end{macrocode}
% Save the full form of the key in the auxiliary file. Obviously, do
% it only for subentries. The full form contains whatever arguments
% were given to the non-last component.
% \begin{macrocode}
- if={strequal(key(),content())}{}{
- TeX={%
- \immediate\write\forestindex at out{%
- \string\indexdefineshortkey{\forestoption{key}}{\forestoption{content}}%
- }%
- }
+ if key/.process={O}{content} {} {%
+ if short={
+ TeX and memoize/.expanded={%
+ \noexpand\immediate\noexpand\write\noexpand\forestindex at out{%
+ \noexpand\string\noexpand\indexdefineshortkey\noexpand\unexpanded{{\forestoption{key}}{\forestoption{content}}}%
+ }%
+ }{}%
}
}
- },
+ }
}
% \end{macrocode}
% Load settings from the auxiliary file into the global style. Warn
@@ -584,7 +604,9 @@
\pgfkeysifdefined{/forest/@@index/#1/. at cmd}{%
\forestindex at loadsettings@warning{#1}%
}{}%
- \forestset{@@index/#1/.global style={#2}}%
+ % #s in #2 are doubled; the following \def removes one layer of doubling
+ \def\forest at temp{#2}%
+ \forestset{@@index/#1/.global style/.expand once=\forest at temp}%
}
\def\forestindex at loadsettings@warning#1{%
\PackageWarning{forest-index}{Forest index key "#1" was configured more than once!
@@ -665,8 +687,8 @@
normal color/.initial=blue,
definition color/.initial=red,
example color/.initial=darkgreen,
- print in color/.style={if stage={print}{result=\protect\textcolor{%
- \pgfkeysvalueof{/forest/#1 color}}{##1}}{}},
+ print in color/.style={if stage={print}{result/.expanded=\noexpand\protect\noexpand\textcolor{%
+ \pgfkeysvalueof{/forest/#1 color}}{\unexpanded{##1}}}{}},
print in color/.default=\forestregister{index entry type},
% \end{macrocode}
% Use this style in |..._format| keylists if you want the index
@@ -720,9 +742,10 @@
\forestset{
declare toks register=default,
default={},
- item/.style={result/.wrap 4 pgfmath args={%
- \item[,##2,##3]{##4}%
- }{}{default}{print_form("!parent")}{result},
+ item/.style={
+ result/.process= {_RORw4}
+ {} {default} {!parent.print form} {result}
+ {\item[,##2,##3]{##4}},
},
}
% \end{macrocode}
@@ -744,6 +767,10 @@
\long\def\pgfkeysglobalsetvalue#1#2{%
\pgfkeys at temptoks{#2}\expandafter\xdef\csname pgfk@#1\endcsname{\the\pgfkeys at temptoks}%
}
+\forestset{
+ % unlike pgfmath function strequal, |if strequal| does not expand the compared args!
+ if strequal/.code n args={4}{\ifstrequal{#1}{#2}{\pgfkeysalso{#3}}{\pgfkeysalso{#4}}},
+}
% \end{macrocode}
% Begin and end group, \foRest;-style:
% \begin{macrocode}
@@ -752,7 +779,92 @@
endgroup/.code={\endgroup},
}
% \end{macrocode}
-%
+%
+% \subsubsection{Memoize}
+%
+% Quick and dirty memoization. Single argument macros only. Does not support nesting.
+%
+% \begin{macrocode}
+\newtoks\forest at memo@key
+\newtoks\forest at memo
+\newif\ifforest at memoizing@now@
+\newif\ifforest at memoizing@ok@
+\newif\ifforest at execandmemoize@
+\def\forest at memoize#1{% #1 = \cs
+ \cslet{forest at memo@orig@\string#1}#1%
+ \def#1##1{%
+ \ifforest at memoizing@now@
+ \forest at globalsaveandrestoreifcs{forest at execandmemoize@}{%
+ \global\forest at execandmemoize@false
+ \csname forest at memo@orig@\string#1\endcsname{##1}%
+ }%
+ \else
+ \expandafter\global\expandafter\forest at memo@key\expandafter{\detokenize{forest at memo@#1{##1}}}%
+ \ifcsname\the\forest at memo@key\endcsname
+ \@escapeifif{\csname\the\forest at memo@key\endcsname}%
+ \else
+ \@escapeifif{%
+ \global\forest at memo{}%
+ \global\forest at memoizing@ok at true
+ \global\forest at memoizing@now at true
+ \global\forest at execandmemoize@true
+ \csname forest at memo@orig@\string#1\endcsname{##1}%
+ \global\forest at execandmemoize@false
+ \global\forest at memoizing@now at false
+ \ifforest at memoizing@ok@
+ \csxdef{\the\forest at memo@key}{\the\forest at memo}%
+ \immediate\write\forest at memo@out{%
+ \noexpand\forest at memo@load{\the\forest at memo@key}{\the\forest at memo}%
+ }%
+ \fi
+ }%
+ \fi
+ \fi
+ }%
+}
+\def\forest at memo@load#1#2{%
+% \end{macrocode}
+% The following two |\def|s remove one level of hash-doubling from the
+% arguments, introduced by |\write|.
+% \begin{macrocode}
+ \def\forest at temp@key{#1}%
+ \def\forest at temp@value{#2}%
+ \csxdef{\detokenize\expandafter{\forest at temp@key}}{\expandonce\forest at temp@value}%
+ \immediate\write\forest at memo@out{%
+ \noexpand\forest at memo@load{\detokenize\expandafter{\forest at temp@key}}{\detokenize\expandafter{\forest at temp@value}}%
+ }%
+}
+\forestset{
+ TeX and memoize/.code={\forest at execandmemoize{#1}},
+}
+\def\forest at execandmemoize#1{%
+ \ifforest at execandmemoize@
+ \let\forest at memo@next\forest at execandmemoize@
+ \else
+ \let\forest at memo@next\@gobble
+ \fi
+ \forest at memo@next{#1}%
+ #1%
+}
+\def\forest at execandmemoize@#1{%
+ \gapptotoks\forest at memo{#1}%
+}
+\def\forest at memo@filename{\jobname.memo}
+\newwrite\forest at memo@out
+\immediate\openout\forest at memo@out=\forest at memo@filename.tmp
+\IfFileExists{\forest at memo@filename}{%
+ \input\forest at memo@filename\relax
+}{}%
+\AtEndDocument{%
+ \immediate\closeout\forest at memo@out
+ \forest at file@copy{\forest at memo@filename.tmp}{\forest at memo@filename}%
+}
+% \end{macrocode}
+% Commenting the following line turns off memoization.
+% \begin{macrocode}
+\forest at memoize\forestindex at index@
+% \end{macrocode}
+%
% \subsubsection*{Initialize}
%
% Declare category ``@unknown''.
Modified: trunk/Master/texmf-dist/source/latex/forest/forest-libs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/forest/forest-libs.dtx 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/source/latex/forest/forest-libs.dtx 2016-12-06 00:28:11 UTC (rev 42640)
@@ -1,9 +1,9 @@
-% \CheckSum{235}
+% \CheckSum{236}
% \iffalse meta-comment
% forest-libs.dtx
%% `forest-libs' is a collection of libraries for package `forest'.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -70,13 +70,12 @@
}
% \end{macrocode}
%
-% There's no linguistics without c-command\footnote{The definition of c-command is as follows: a node c-commands its siblings and their subtrees.} \dots
+% There's no linguistics without c-command\footnote{The definition of c-command is as follows: a node c-commands its siblings and their descendants.} \dots
% \begin{syntax}
% \indexitem{step>c-commanded} Visit all the nodes c-commanded by the current node.
% \indexitem{step>c-commanders} Visit all the c-commanders of the current node, starting from the closest.
%
% \begin{forestexample}[tree bin=minipage,index={branch',c-commanded}]
-% ``manual'' c-command:\\[1ex]
% \begin{forest}
% [VP
% [DP[John]]
@@ -190,7 +189,7 @@
% xlist/.style={
% phantom,
% for children={no edge,replace by={[,append,
-% delay={content/.wrap pgfmath arg={\@alph{##1}.}{n()+#1}}
+% delay={content/.wrap pgfmath arg={\csname @alph\endcsname{##1}.}{n()+#1}}
% ]}}
% },
% xlist/.default=0
@@ -239,7 +238,7 @@
for tree'={
TeX={[%
% \end{macrocode}
-% Complication: \index{content format} must be expanded in advance, to correctly process tabular environments implicitely loaded by \index{align}|=|\index{value=align>center}, which is the default in this library. (Not that one would want a multiline output in the bracket representation, but it's better than crashing.)
+% Complication: \index{content format} must be expanded in advance, to correctly process tabular environments implicitely loaded by \index{align}|=|\index{value of=align>center}, which is the default in this library. (Not that one would want a multiline output in the bracket representation, but it's better than crashing.)
% \begin{macrocode}
\edef\forestdrawbracketscontentformat{\foresteoption{content format}}%
},
@@ -374,29 +373,28 @@
%\fi
% \librarysection{edges}
% \begin{macrocode}
-\ProvidesForestLibrary{edges}[2015/11/14 v0.1]
+\ProvidesForestLibrary{edges}[2016/12/05 v0.1.1]
% \end{macrocode}
%
% \begin{syntax}
%
-% \indexitem{node key>forked edge}
+% \indexitem{node key>forked edge'}
%
% Sets a forked edge to the current node. Arbitrary growth direction and node rotation are
% supported.
%
-% Using this key does \emph{not} change the current values of \index{option>parent anchor} and
-% \index{option>child anchor}.
-%
-% \indexitem{node key>forked edges}
+% \indexitem{node key>forked edge}
%
-% Sets forked edges to the entire (sub)tree rooted in the current node. Arbitrary growth
-% direction and node rotation are supported.
+% Like \index{forked edge'}, but it also sets \index{option>parent anchor} and \index{option>child
+% anchor} to the likely values of \index{anchor>children} and \index{anchor>parent}, respectively.
%
-% \index{option>parent anchor} and \index{option>child anchor} are set to \index{anchor>children} and
-% \index{anchor>parent}, repectively.
+% \indexitem(tree){node key>forked edges}|=|\meta{nodewalk}
%
-% \indexitem{option>fork sep} The \index{forest cs>l}-distance between the parent anchor and the
-% fork.
+% Invokes \index{forked edge} for all nodes in the \meta{nodewalk}, by default the entire (sub)tree
+% rooted in the current node.
+%
+% \indexitem{option>fork sep} The \index{forest cs>l}-distance between the parent anchor and the
+% fork.
%
% \end{syntax}
%
@@ -421,19 +419,23 @@
% \end{forest}
% \end{forestexample}
%
-% See how \indexex{anchor>parent anchor} and \indexex{anchor>parent anchor} are used in the
-% definition of |forked_edge| to easily take care of arbitrary \index{grow} and \index{rotate}.
+% See how growth direction based anchors \indexex{anchor>children} and \indexex{anchor>parent} are
+% used in the definition below to easily take care of arbitrary \index{grow} and
+% \index{rotate}.
% \begin{macrocode}
\forestset{
declare dimen={fork sep}{0.5em},
- forked edge/.style={
- edge={rotate/.pgfmath=grow()},
+ forked edge'/.style={
+ edge={rotate/.option=!parent.grow},
edge path'={(!u.parent anchor) -- ++(\forestoption{fork sep},0) |- (.child anchor)},
},
- forked edges/.style={
- for tree={parent anchor=children},
- for descendants={child anchor=parent,forked edge}
+ forked edge/.style={
+ on invalid={fake}{!parent.parent anchor=children},
+ child anchor=parent,
+ forked edge',
},
+ forked edges/.style={for nodewalk={#1}{forked edge}},
+ forked edges/.default=tree,
}
% \end{macrocode}
%
@@ -481,7 +483,7 @@
declare dimen register=folder indent,
folder indent=.45em,
folder/.style={
- parent anchor=parent last,
+ parent anchor=-children last,
anchor=parent first,
calign=child,
calign primary child=1,
@@ -488,7 +490,7 @@
for children={
child anchor=parent,
anchor=parent first,
- edge={rotate/.pgfmath=grow()},
+ edge={rotate/.option=!parent.grow},
edge path'/.expanded={
([xshift=\forestregister{folder indent}]!u.parent anchor) |- (.child anchor)
},
Modified: trunk/Master/texmf-dist/source/latex/forest/forest.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/forest/forest.dtx 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/source/latex/forest/forest.dtx 2016-12-06 00:28:11 UTC (rev 42640)
@@ -1,9 +1,9 @@
-% \CheckSum{12887}
+% \CheckSum{16573}
% \iffalse meta-comment
% forest.dtx
%% `forest' is a `pgf/tikz'-based package for drawing (linguistic) trees.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -83,7 +83,7 @@
%
% \section{Identification}
% \begin{macrocode}
-\ProvidesPackage{forest}[2016/04/09 v2.0.3 Drawing (linguistic) trees]
+\ProvidesPackage{forest}[2016/12/05 v2.1 Drawing (linguistic) trees]
\RequirePackage{tikz}[2013/12/13]
\usetikzlibrary{shapes}
@@ -97,8 +97,74 @@
\RequirePackage{environ}
\RequirePackage{xparse}
-% \usepackage[trace]{trace-pgfkeys}
-
+\RequirePackage{inlinedef}
+\newtoks\ID at usercommands{}
+\newcommand\NewInlineCommand[3][0]{%
+ \newcommand#2[#1]{#3}%
+ \ID at usercommands\xa{%
+ \the\ID at usercommands
+ \ifx\@foo#2%
+ \def\next{\ID at expandunsafe#2}%
+ \fi
+ }%
+}
+\def\@ExpandIfTF#1{%
+ \csname
+ % I'm not 100% sure if this plays well in every situation
+ \csname if#1\endcsname
+ @firstoftwo%
+ \else
+ @secondoftwo%
+ \fi
+ \endcsname
+}
+\patchcmd{\ID at switch}
+ {\ifcat\noexpand\@foo\space}
+ {\the\ID at usercommands\ifcat\noexpand\@foo\space}
+ {%
+ \NewInlineCommand[2]\ExpandIfT{%
+ \MultiExpand{3}{%
+ \@ExpandIfTF{#1}{#2}{}%
+ }%
+ }
+ \NewInlineCommand[2]\ExpandIfF{%
+ \MultiExpand{3}{%
+ \@ExpandIfTF{#1}{}{#2}%
+ }%
+ }
+ \NewInlineCommand[3]\ExpandIfTF{%
+ \MultiExpand{3}{%
+ \@ExpandIfTF{#1}{#2}{#3}%
+ }%
+ }%
+ \newcommand\InlineNoDef[1]{%
+ \begingroup
+ % Define a few ``quarks''
+ \def\Expand{\Expand}\def\Super{\Super}%
+ \def\UnsafeExpand{\UnsafeExpand}\def\MultiExpand{\MultiExpand}%
+ \def\Recurse{\Recurse}\def\NoExpand{\NoExpand}%
+ \def\Q at END{\Q at END}%
+ % Define a toks register
+ \ID at toks{}%
+ % Signal that we need to look for a star
+ \@testtrue\ID at starfalse\ID at starstarfalse\ID at bangfalse
+ % Start scanning for \def or \gdef
+ \ID at scan#1\Q at END{}%
+ \expandafter\endgroup
+ %\expandafter\@firstofone
+ \the\ID at toks
+ }%
+ }%
+ {%
+ \PackageWarning{forest}{Could not patch inlinedef! Disabling it. Except in some special situations (nested arrays), stuff will probably still work, but there's no guarantee. Please report this situation to the author (but check first if a new version already exists).}{}%
+ \let\Inline\relax
+ \def\Expand#1{#1}%
+ \def\MultiExpand#1#2{#2}%
+ \def\InlineNoDef#1{#1}%
+ \def\ExpandIfT#1#2{\@ExpandIfTF{#1}{#2}{}}%
+ \def\ExpandIfF#1#2{\@ExpandIfTF{#1}{}{#2}}%
+ \def\ExpandIfTF#1#2#3{\@ExpandIfTF{#1}{#2}{#3}}%
+ }
% \end{macrocode}
%
% |/forest| is the root of the key hierarchy.
@@ -114,12 +180,15 @@
\newif\ifforest at install@keys at to@tikz at path@
\newif\ifforestdebugnodewalks
\newif\ifforestdebugdynamics
+\newif\ifforestdebugprocess
+\newif\ifforestdebugtemp
+\newif\ifforestdebug
\def\forest at compat{}
\forestset{package at options/.cd,
external/.is if=forest at external@,
tikzcshack/.is if=foresttikzcshack,
tikzinstallkeys/.is if=forest at install@keys at to@tikz at path@,
- compat/.store in=\forest at compat,
+ compat/.code={\appto\forest at compat{,#1}},
compat/.default=most,
.unknown/.code={% load library
\eappto\forest at loadlibrarieslater{%
@@ -127,10 +196,11 @@
\noexpand\forestapplylibrarydefaults{\pgfkeyscurrentname}%
}%
},
- debug/.code={\pgfqkeys{/forest/package at options/debug}{#1}},
- debug/.default={nodewalks,dynamics},
+ debug/.code={\forestdebugtrue\pgfqkeys{/forest/package at options/debug}{#1}},
+ debug/.default={nodewalks,dynamics,process},
debug/nodewalks/.is if=forestdebugnodewalks,
debug/dynamics/.is if=forestdebugdynamics,
+ debug/process/.is if=forestdebugprocess,
}
\forest at install@keys at to@tikz at path@true
\foresttikzcshacktrue
@@ -141,10 +211,17 @@
\forcsvlist\useforestlibrary@@{#3}%
\IfBooleanT{#1}{\forestapplylibrarydefaults{#3}}%
}
-\def\useforestlibrary@#1#2{\RequirePackage[#1]{forest-lib-#2}}
+\def\useforestlibrary@#1#2{%
+ \RequirePackage[#1]{forest-lib-#2}%
+ \csuse{forest at compat@libraries@#2}%
+}
\def\forestapplylibrarydefaults#1{\forcsvlist\forestapplylibrarydefaults@{#1}}
\def\forestapplylibrarydefaults@#1{\forestset{libraries/#1/defaults/.try}}
-\NewDocumentCommand\ProvidesForestLibrary{m O{}}{\ProvidesPackage{forest-lib-#1}[#2]}
+\NewDocumentCommand\ProvidesForestLibrary{m O{}}{%
+ \ProvidesPackage{forest-lib-#1}[#2]%
+ \csdef{forest at libraries@loaded@#1}{}%
+}
+\def\forest at iflibraryloaded#1#2#3{\ifcsdef{forest at libraries@loaded@#1}{#2}{#3}}
\ProcessPgfPackageOptions{/forest/package at options}
% \end{macrocode}
% \section{Patches}
@@ -184,6 +261,11 @@
%
% \section{Utilities}
%
+% This is handy.
+% \begin{macrocode}
+\def\forest at empty{}
+% \end{macrocode}
+%
% Escaping |\if|s.
% \begin{macrocode}
\long\def\@escapeif#1#2\fi{\fi#1}
@@ -190,7 +272,25 @@
\long\def\@escapeifif#1#2\fi#3\fi{\fi\fi#1}
\long\def\@escapeififif#1#2\fi#3\fi#4\fi{\fi\fi\fi#1}
% \end{macrocode}
-%
+%
+% \begin{macrocode}
+\def\forest at repeat@n at times#1{% #1=n, #2=code
+ \expandafter\forest at repeat@n at times@\expandafter{\the\numexpr#1}}
+\def\forest at repeat@n at times@#1{%
+ \ifnum#1>0
+ \@escapeif{%
+ \expandafter\forest at repeat@n at times@@\expandafter{\the\numexpr#1-1}%
+ }%
+ \else
+ \expandafter\@gobble
+ \fi
+}
+\def\forest at repeat@n at times@@#1#2{%
+ #2%
+ \forest at repeat@n at times@{#1}{#2}%
+}
+% \end{macrocode}
+%
% A factory for creating |\...loop...| macros.
% \begin{macrocode}
\def\newloop#1{%
@@ -508,6 +608,7 @@
\def\forest at temp@macro####1{#4}%
\csname forest at temp#5\endcsname
\edef\forest at temp@value{\ifforest at temp\expandafter\forestOv\expandafter{\expandafter\forest at setter@node\expandafter}\else\expandafter\forestrv\fi{#2}}%
+ %\expandafter\expandafter\expandafter\pgfkeysalso\expandafter\expandafter\expandafter{\expandafter\forest at temp@macro\expandafter{\forest at temp@value}}% ??? how many expansions are really needed?
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\pgfkeysalso\expandafter\expandafter\expandafter{\expandafter\forest at temp@macro\expandafter{\forest at temp@value}}%
}%
}{}%
@@ -559,8 +660,853 @@
\fi
}%
}
+\forestset{
+ show register/.code={%
+ \forestrget{#1}\foresttemp
+ \typeout{Forest register "#1"=\expandafter\detokenize\expandafter{\foresttemp}}%
+ },
+}
% \end{macrocode}
+% \subsection{Arrays}
+%
+% \begin{macrocode}
+\def\forest at newarray#1{%
+ \forest at tempfalse % non-global
+ {%
+ \escapechar=-1
+ \expandafter\escapechar\expandafter\count@\expandafter
+ }%
+ \expandafter\forest at newarray@\expandafter{\string#1}%
+}
+\def\forest at newglobalarray#1{%
+ \forest at temptrue % global
+ {%
+ \escapechar=-1
+ \expandafter\escapechar\expandafter\count@\expandafter
+ }%
+ \expandafter\forest at newarray@\expandafter{\string#1}%
+}
+\def\forest at array@empty at error#1{%
+ \PackageError{forest}{Cannot pop from empty array "#1".}{}}%
+\def\forest at array@oub at error#1#2{%
+ \PackageError{forest}{#2 is out of bounds of array "#1"
+ (\the\csuse{#1M}--\the\csuse{#1N}).}{}}%
+% \end{macrocode}
+% Define array macros. For speed, we define most of them to be ``direct'', i.e.\ cointain the resolved control sequences specific to this array.
+% \begin{macrocode}
+\def\forest at newarray@#1{%
+ % array bounds: M <= i < N
+ \expandafter\newcount\csname#1M\endcsname
+ \expandafter\newcount\csname#1N\endcsname
+ \csedef{#1clear}{%
+ \ifforest at temp\global\fi\expandonce{\csname#1M\endcsname}0
+ \ifforest at temp\global\fi\expandonce{\csname#1N\endcsname}0
+ }%
+ \csedef{#1ifempty}{%
+ \noexpand\ifnum\expandonce{\csname#1M\endcsname}<\expandonce{\csname#1N\endcsname}\relax
+ \unexpanded{\expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi}%
+ }%
+ \csedef{#1length}{% a numexpr
+ \noexpand\numexpr\expandonce{\csname#1N\endcsname}-\expandonce{\csname#1M\endcsname}\relax
+ }%
+ \csedef{#1checkrange}##1##2{% args can be \numexprs
+ \noexpand\forest at tempfalse
+ \noexpand\ifnum\numexpr##1<\expandonce{\csname#1M\endcsname}\relax
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifnum\numexpr##2>\expandonce{\csname#1N\endcsname}\relax
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifforest at temp
+ \noexpand\forest at array@oub at error{#1}{Range "\noexpand\number\noexpand\numexpr##1\relax--\noexpand\number\noexpand\numexpr##2\relax"}%
+ \noexpand\fi
+ }%
+ \csedef{#1checkindex}##1{% arg can be a \numexpr
+ \noexpand\forest at tempfalse
+ \noexpand\ifnum\numexpr##1<\expandonce{\csname#1M\endcsname}\relax
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifnum\numexpr##1<\expandonce{\csname#1N\endcsname}\relax
+ \noexpand\else
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifforest at temp
+ \noexpand\forest at array@oub at error{#1}{Index "\noexpand\number\noexpand\numexpr##1\relax"}%
+ \noexpand\fi
+ }%
+ \csedef{#1get}##1##2{% ##1 = index, ##2 = receiving cs
+ \expandonce{\csname#1checkindex\endcsname}{##1}%
+ \noexpand\letcs##2{#1##1}%
+ }%
+ \csedef{#1get@}##1##2{% ##1 = index, ##2 = receiving cs (don't check bounds)
+ \noexpand\letcs##2{#1##1}%
+ }%
+ \csedef{#1toppop}##1{% ##1 = receiving cs
+ \expandonce{\csname#1ifempty\endcsname}{%
+ \noexpand\forest at array@empty at error{#1}%
+ }{%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}-1
+ \noexpand\letcs\noexpand##1{#1\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ }%
+ }%
+ \InlineNoDef{\csdef{#1bottompop}##1{% ##1 = receiving cs
+ \Expand{\csname#1ifempty\endcsname}{%
+ \forest at array@empty at error{#1}%
+ }{%
+ \letcs##1{#1\the\Expand{\csname#1M\endcsname}}%
+ \ExpandIfT{forest at temp}\global\advance\Expand{\csname#1M\endcsname 1}%
+ }%
+ }}%
+ % \csdef{#1bottompop}##1{}% we need this as \Inline chokes on \let\macro=\relax
+ % \expandafter\Inline\expandafter\def\csname#1bottompop\endcsname##1{% ##1 = receiving cs
+ % \Expand{\csname#1ifempty\endcsname}{%
+ % \forest at array@empty at error{#1}%
+ % }{%
+ % \letcs##1{#1\the\Expand{\csname#1M\endcsname}}%
+ % \ExpandIfT{forest at temp}\global\advance\Expand{\csname#1M\endcsname 1}%
+ % }%
+ % }%
+ % \csedef{#1bottompop}##1{% ##1 = receiving cs
+ % \expandonce{\csname#1ifempty\endcsname}{%
+ % \noexpand\forest at array@empty at error{#1}%
+ % }{%
+ % \noexpand\letcs\noexpand##1{#1\noexpand\the\expandonce{\csname#1M\endcsname}}%
+ % \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}1
+ % }%
+ % }%
+ \csedef{#1setappend}##1{% ##1 = definition
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi
+ {#1\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ {\noexpand\unexpanded{##1}}%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ }%
+ \csedef{#1setappend@}##1##2{% ##1 = continue by, ##2 = definition
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi
+ {#1\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ {\noexpand\unexpanded{##2}}%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ ##1%
+ }%
+ \csedef{#1setprepend}##1{% ##1 = definition
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}-1
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi
+ {#1\noexpand\the\expandonce{\csname#1M\endcsname}}%
+ {\noexpand\unexpanded{##1}}%
+ }%
+ \csedef{#1esetappend}##1{% ##1 = definition
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi{#1\noexpand\the\expandonce{\csname#1N\endcsname}}{##1}%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ }%
+ \csedef{#1esetprepend}##1{% ##1 = definition
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}-1
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi{#1\noexpand\the\expandonce{\csname#1M\endcsname}}{##1}%
+ }%
+ \csedef{#1letappend}##1{% ##1 = cs
+ \ifforest at temp\noexpand\expandafter\noexpand\global\fi\noexpand\expandafter\noexpand\let
+ \noexpand\csname#1\noexpand\the\expandonce{\csname#1N\endcsname}\noexpand\endcsname
+ ##1%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ }%
+ \csedef{#1letprepend}##1{% ##1 = cs
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}-1
+ \ifforest at temp\noexpand\expandafter\noexpand\global\fi\noexpand\expandafter\noexpand\let
+ \noexpand\csname#1\noexpand\the\expandonce{\csname#1M\endcsname}\noexpand\endcsname
+ ##1%
+ }%
+% \end{macrocode}
+% I would love to define these only generically, as they will not be called often, but they need to be expandable. Argh.
+% right?
+% \begin{lstlisting}
+% \def\arrayvalues{% <-- \csedef{#1values}
+% \expandafter\expandafter\expandafter\arrayvaluesfromrange %\arrayvaluesfromrange <-- \expandonce{\csname#1valuesfromrange\endcsname}
+% \expandafter\expandafter\expandafter{%
+% \expandafter\the
+% \expandafter\arrayM %\arrayM <-- \expandonce{\csname#1M\endcsname}%
+% \expandafter}%
+% \expandafter{%
+% \the\arrayN %\arrayN <-- \expandonce{\csname#1N\endcsname}%
+% }%
+% }%
+% \end{lstlisting}
+% \begin{macrocode}
+ \csedef{#1values}{%
+ \noexpand\expandafter\noexpand\expandafter\noexpand\expandafter\expandonce{\csname#1valuesfromrange\endcsname}%
+ \noexpand\expandafter\noexpand\expandafter\noexpand\expandafter{%
+ \noexpand\expandafter\noexpand\the
+ \noexpand\expandafter\expandonce{\csname#1M\endcsname}%
+ \noexpand\expandafter}%
+ \noexpand\expandafter{\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ }%
+% \end{macrocode}
+% \begin{lstlisting}
+% \def\arrayvaluesfromrange##1##2{% ##1/##2 = lower/upper bounds (we receive them expanded) <-- \csedef{#1vuesfromrange}
+% \ifnum##1<##2
+% {\expandafter\expandonce\expandafter{\csname#1##1\endcsname}}% here we add braces (for the general case, we might want an arbitrary prefix&suffix)
+% \expandafter\@escapeif\expandafter{\expandafter\arrayvaluesfromrange % <-- \expandonce{\csname#1valuesfromrange\endcsname}%
+% \expandafter{\number\numexpr##1+1}{##2}}%
+% \fi
+% }%
+% \end{lstlisting}
+% As we need this to be expandable, we cannot check the range within the macro. You need to to this on your own using |...checkrange| defined above.
+% \begin{macrocode}
+ \csedef{#1valuesfromrange}##1##2{% ##1/##2 = lower/upper bounds (we receive them expanded)
+ \noexpand\ifnum##1<##2
+ {\noexpand\expandafter\noexpand\expandonce\noexpand\expandafter{\noexpand\csname#1##1\noexpand\endcsname}}% here we add braces (for the general case, we might want an arbitrary prefix&suffix)
+ \noexpand\expandafter\noexpand\@escapeif\noexpand\expandafter{\noexpand\expandafter\expandonce{\csname#1valuesfromrange\endcsname}%
+ \noexpand\expandafter{\noexpand\number\noexpand\numexpr##1+1}{##2}}%
+ \noexpand\fi
+ }%
+% \end{macrocode}
+% Puts all items until |\forest at eov| into the array. After that is done, execute |\forest at topextend@next|. This code is difficult and not run often, so it doesn't need specialized control sequences.
+% \begin{macrocode}
+ \csdef{#1topextend}{\def\forest at array@currentarray{#1}\forest at array@topextend}%
+}
+\def\forest at array@topextend{\futurelet\forest at ate@next at token\forest at ate@checkforspace}
+\def\forest at ate@checkforspace{%
+ \expandafter\ifx\space\forest at ate@next at token
+ \expandafter\forest at ate@havespace
+ \else
+ \expandafter\forest at ate@checkforgroup
+ \fi
+}
+\def\forest at ate@havespace{\expandafter\forest at array@topextend\romannumeral-`0}%
+\def\forest at ate@checkforgroup{%
+ \ifx\forest at ate@next at token\bgroup
+ \expandafter\forest at ate@appendgroup
+ \else
+ \expandafter\forest at ate@checkforeov
+ \fi
+}
+\def\forest at ate@appendgroup{%
+ \expandonce{\csname\forest at array@currentarray setappend@\endcsname}\forest at array@topextend
+}
+\def\forest at ate@checkforeov{%
+ \ifx\forest at ate@next at token\forest at eov
+ \expandafter\forest at ate@finish
+ \else
+ \expandafter\forest at ate@appendtoken
+ \fi
+}
+\def\forest at ate@appendtoken#1{%
+ \expandonce{\csname\forest at array@currentarray setappend\endcsname}{#1}%
+ \forest at array@topextend
+}
+\def\forest at ate@finish\forest at eov{\forest at topextend@next}
+\let\forest at topextend@next\relax
+\forest at newarray\forest at temparray@
+\forest at newglobalarray\forest at global@temparray@
+% \end{macrocode}
%
+%
+% \subsection{Testing for numbers and dimensions}
+% \label{sec:is-count-or-dimen}
+%
+% Test if the argument is an integer (only base 10) that can be assigned to a \TeX\ count register.
+% This is supposed to be a fast, not complete test, as anything not recognized as an integer will be
+% passed on to |pgfmath| (by the code that uses these macros).
+%
+% We support |+|s, |-|s and spaces before the number. We don't support count registers.
+%
+% Dillema? Should |0abc| be interpreted as \TeX\ style (decimal) or PGF style (octal)? We go for
+% \TeX\ style.
+%
+% The return value will hide in \TeX-style |\if|-macro |\forest at isnum| and counter |\forest at isnum@count|.
+%
+% \begin{macrocode}
+\def\forest at eon{ }
+\newif\ifforest at isnum@minus
+\newif\ifforest at isnum
+\def\forest at isnum#1{%
+ \forest at isnum@minusfalse
+ \let\forest at isnum@next\forest at isnum@finish
+% \end{macrocode}
+% Expand in advance, like pgfmath does.
+% \begin{macrocode}
+ \edef\forest at isnum@temp{#1}%
+% \end{macrocode}
+% Add two end-of-value markers. The first one might be eaten by count assignment: that's why there
+% are two and they expand to a space.
+% \begin{macrocode}
+ \expandafter\forest at isnum@a\forest at isnum@temp\forest at eon\forest at eon\forest at END
+ \ifforest at isnum
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\def\forest at isnum@a{\futurelet\forest at isnum@token\forest at isnum@b}
+% \end{macrocode}
+% Test for three special characters: |-|, |+|, and space.
+% \begin{macrocode}
+\def\forest at isnum@minustoggle{%
+ \ifforest at isnum@minus\forest at isnum@minusfalse\else\forest at isnum@minustrue\fi
+}
+\def\forest at isnum@b{%
+ \let\forest at next\forest at isnum@p
+ \ifx-\forest at isnum@token
+ \forest at isnum@minustoggle
+ \let\forest at next\forest at isnum@c
+ \else
+ \ifx+\forest at isnum@token
+ \let\forest at next\forest at isnum@c
+ \else
+ \expandafter\ifx\space\forest at isnum@token
+ \let\forest at next\forest at isnum@s
+ \fi
+ \fi
+ \fi
+ \forest at next
+}
+% \end{macrocode}
+% Eat |+| and |-|.
+% \begin{macrocode}
+\def\forest at isnum@c#1{\forest at isnum@a}%
+% \end{macrocode}
+% Eat the space!
+% \begin{macrocode}
+\def\forest at isnum@s#1{\forest at isnum@a#1}%
+\newcount\forest at isnum@count
+% \end{macrocode}
+% Check for |0|. Why? If we have one, we know that the initial argument started with a number, so
+% we have a chance that it is a number even if our assignment will yield $0$. If we have no |0| and the assignment yields $0$, we know we don't have a number.
+% \begin{macrocode}
+\def\forest at isnum@p{%
+ \ifx0\forest at isnum@token
+ \let\forest at next\forest at isnum@next
+ \else
+ \let\forest at next\forest at isnum@nz@
+ \fi
+ \forest at isnumtrue
+ \afterassignment\forest at isnum@q\forest at isnum@count\ifforest at isnum@minus-\fi0%
+}
+\def\forest at isnum@q{%
+ \futurelet\forest at isnum@token\forest at next
+}
+\def\forest at isnum@nz@{%
+ \ifnum\forest at isnum@count=0
+ \forest at isnumfalse
+ \fi
+ \forest at isnum@next
+}
+% \end{macrocode}
+% This is the end of testing for an integer. If we have left-over stuff (|#1|), this was not a number.
+% \begin{macrocode}
+\def\forest at isnum@finish#1\forest at END{%
+ \ifx\forest at isnum@token\forest at eon
+ \else
+ \forest at isnumfalse
+ \fi
+}
+% \end{macrocode}
+%
+% Is it a dimension? We support all \TeX's units but |true| units. Also supported are unitless
+% dimensions (i.e.\ decimal numbers), which are interpreted as |pt|s, as in pgfmath.
+%
+% The return value will hide in \TeX-style |\if|-macro |\forest at isdim| and counter |\forest at isdim@dimen|.
+%
+% \begin{macrocode}
+\newcount\forest at isdim@nonintpart
+\newif\ifforest at isdim
+\def\forest at isdim#1{%
+ \forest at isdimfalse
+ \forest at isnum@minusfalse
+ \def\forest at isdim@leadingzeros{}%
+ \forest at isdim@nonintpart=0
+ \def\forest at isdim@unit{pt}%
+ \let\forest at isnum@next\forest at isdim@checkfordot
+ \edef\forest at isnum@temp{#1}%
+% \end{macrocode}
+% 4 end-of-value markers (|forest at eon|): one can be eaten by number (after the dot), two by a non-existing unit.
+% \begin{macrocode}
+ \expandafter\forest at isnum@a\forest at isnum@temp\forest at eon\forest at eon\forest at eon\forest at eon\forest at END
+ \ifforest at isdim
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\def\forest at isdim@checkfordot{%
+ \ifx.\forest at isnum@token
+ \expandafter\forest at isdim@dot
+ \else
+ \ifx,\forest at isnum@token
+ \expandafter\expandafter\expandafter\forest at isdim@dot
+ \else
+ \expandafter\expandafter\expandafter\forest at isdim@nodot
+ \fi
+ \fi
+}
+\def\forest at isdim@nodot{%
+ \ifforest at isnum
+% \end{macrocode}
+% No number, no dot, so not a dimension.
+% \begin{macrocode}
+ \expandafter\forest at isdim@checkforunit
+ \else
+ \expandafter\forest at isdim@finish at nodim
+ \fi
+}
+\def\forest at isdim@dot#1{% #1=. or ,
+ \futurelet\forest at isnum@token\forest at isdim@collectzero
+}
+\def\forest at isdim@collectzero{%
+ \ifx0\forest at isnum@token
+ \expandafter\forest at isdim@collectzero@
+ \else
+ \expandafter\forest at isdim@getnonintpart
+ \fi
+}
+\def\forest at isdim@collectzero@#1{% #1 = 0
+ \appto\forest at isdim@leadingzeros{0}%
+ \futurelet\forest at isnum@token\forest at isdim@collectzero
+}
+\def\forest at isdim@getnonintpart{%
+ \afterassignment\forest at isdim@checkforunit\forest at isdim@nonintpart0%
+}
+% \end{macrocode}
+% Nothing else should be defined in |\forest at unit@| namespace.
+% \begin{macrocode}
+\def\forest at def@unit#1{\csdef{forest at unit@#1}{#1}}
+\forest at def@unit{em}
+\forest at def@unit{ex}
+\forest at def@unit{pt}
+\forest at def@unit{pc}
+\forest at def@unit{in}
+\forest at def@unit{bp}
+\forest at def@unit{cm}
+\forest at def@unit{mm}
+\forest at def@unit{dd}
+\forest at def@unit{cc}
+\forest at def@unit{sp}
+\def\forest at isdim@checkforunit#1#2{%
+ \lowercase{\edef\forest at isnum@temp{\detokenize{#1#2}}}%
+ \ifcsname forest at unit@\forest at isnum@temp\endcsname
+ \let\forest at isdim@next\forest at isdim@finish at dim
+ \edef\forest at isdim@unit{\csname forest at unit@\forest at isnum@temp\endcsname}%
+ \else
+ \ifx#1\forest at eon
+ \let\forest at isdim@next\forest at isdim@finish at dim
+ \else
+ \let\forest at isdim@next\forest at isdim@finish at nodim
+ \fi
+ \fi
+ \forest at isdim@next
+}
+\def\forest at isdim@finish at dim{%
+ \futurelet\forest at isnum@token\forest at isdim@finish at dim@a
+}
+\def\forest at isdim@finish at dim@a{%
+ \expandafter\ifx\space\forest at isnum@token
+ \expandafter\forest at isdim@finish at dim@b
+ \else
+ \expandafter\forest at isdim@finish at dim@c
+ \fi
+}
+\expandafter\def\expandafter\forest at isdim@finish at dim@b\space{% eat one space
+ \futurelet\forest at isnum@token\forest at isdim@finish at dim@c
+}
+\def\forest at isdim@finish at dim@c#1\forest at END{%
+ \ifx\forest at isnum@token\forest at eon
+ \forest at isdimtrue
+ \forest at isdim@dimen\the\forest at isnum@count.\forest at isdim@leadingzeros\the\forest at isdim@nonintpart\forest at isdim@unit\relax
+ \else
+ \forest at isdimfalse
+ \fi
+}
+\def\forest at isdim@finish at nodim#1\forest at END{%
+ \forest at isdimfalse
+}
+\newdimen\forest at isdim@dimen
+ % \long\def\@firstofthree#1#2#3{#3} % defined by LaTeX
+\long\def\@firstofthree#1#2#3{#1}
+\long\def\@secondofthree#1#2#3{#2}
+\def\forest at isnumdim#1{%
+ \forest at isdim{#1}{%
+ \forest at isnumdim@
+ }{%
+ \@thirdofthree
+ }%
+}
+\def\forest at isnumdim@{%
+ \ifforest at isnum
+ \expandafter\@firstofthree
+ \else
+ \expandafter\@secondofthree
+ \fi
+}
+% \end{macrocode}
+%
+%
+% \subsection{forestmath}
+%
+% We imitate |pgfmath| a lot, but we remember the type of the result so that we can use \TeX's
+% primitives when possible.
+% \begin{macrocode}
+\def\forestmathtype at generic{_} % generic (token list)
+\def\forestmathtype at count{n} % integer
+\def\forestmathtype at dimen{d} % a dimension: <decimal> pt
+\def\forestmathtype at unitless{P} % <decimal> (a unitless dimension) (P because pgfmath returns such numbers)
+\def\forestmathtype at textasc{t} % text (ascending)
+\def\forestmathtype at textdesc{T} % text (descending)
+\def\forestmathtype at array{a} % array - internal
+\def\forestmathtype at none{} % internal (for requests - means whatever)
+\def\forestmathresult{}
+\let\forestmathresulttype\forestmathtype at generic
+% \end{macrocode}
+% |\forest at tryprocess| takes three ``arguments''. The first is a forestmath expression, delimited
+% by |\forest at spacegen|: if it starts with a |>|, we take it to be a |.process| expression, evaluate
+% it using |\forest at process|, and execute the second argument; it it doesn't, we execute the third
+% argument.
+% \begin{macrocode}
+\def\forest at tryprocess{%
+ \expandafter\forest at tryprocess@a\romannumeral-`0}
+\def\forest at tryprocess@a{\futurelet\forest at temp@token\forest at tryprocess@b}
+\def\forest at tryprocess@b{%
+ \ifx>\forest at temp@token
+ \expandafter\forest at tryprocess@yes
+ \else
+ \expandafter\forest at tryprocess@no
+ \fi
+}
+\def\forest at spacegen{ \forest at spacegen}
+\def\forest at tryprocess@yes#1#2\forest at spacegen{%
+ \forest at process{false}#2\forest at eov
+ \@firstoftwo
+}
+\def\forest at tryprocess@no#1\forest at spacegen{\@secondoftwo}
+% \end{macrocode}
+% Forestmath versions of pgfmath macros. They accept process and pgfmath expressions, as described
+% above. In the case of a pgfmath expression, they use |\forest at isnum| and |\forest at isdim| for to
+% see if they can avoid pgfmath evaluation. (These checks are generally faster than pgfmath's fast
+% track.)
+% \begin{macrocode}
+\def\forestmathsetcount#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ #1=\forest at process@result\relax
+ }{%
+ \forestmathsetcount@#1{#2}%
+ }%
+}
+\def\forestmathsetcount@#1#2{%
+ \forest at isnum{#2}{%
+ #1=\forest at isnum@count
+ }{%
+ \pgfmathsetcount#1{#2}%
+ }%
+}
+\def\forestmathsetlength#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ #1=\forest at process@result\relax
+ }{%
+ \forestmathsetlength@#1{#2}%
+ }%
+}
+\def\forestmathsetlength@#1#2{%
+ \forest at isdim{#2}{%
+ #1=\forest at isdim@dimen
+ }{%
+ \pgfmathsetlength#1{#2}%
+ }%
+}
+\def\forestmathtruncatemacro#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ \forest at temp@count=\forest at process@result\relax
+ \edef#1{\the\forest at temp@count}%
+ }{%
+ \forestmathtruncatemacro@#1{#2}%
+ }%
+}
+\def\forestmathtruncatemacro@#1#2{%
+ \forest at isnum{#2}{%
+ \edef#1{\the\forest at isnum@count}%
+ }{%
+ \pgfmathtruncatemacro#1{#2}%
+ }%
+}
+\def\forestmathsetlengthmacro#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ \forest at temp@dimen=\forest at process@result\relax
+ \edef#1{\the\forest at temp@dimen}%
+ }{%
+ \forestmathsetlengthmacro@#1{#2}%
+ }%
+}
+\def\forestmathsetlengthmacro@#1#2{%
+ \forest at isdim{#2}{%
+ \edef#1{\the\forest at isdim@dimen}%
+ }{%
+ \pgfmathsetlengthmacro#1{#2}%
+ }%
+}
+\def\forestmathsetmacro#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ \let#1\forest at process@result
+ \let\forestmathresulttype\forest at process@result at type
+ }{%
+ \forestmathsetmacro@#1{#2}%
+ \def\forestmathresulttype{P}%
+ }%
+}
+\def\forestmathsetmacro@#1#2{%
+ \forest at isdim{#2}{%
+ \edef#1{\expandafter\Pgf at geT\the\forest at isdim@dimen}%
+ }{%
+ \pgfmathsetmacro#1{#2}%
+ }%
+}
+\def\forestmathparse#1{%
+ \forest at tryprocess#1\forest at spacegen{%
+ \let\forestmathresult\forest at process@result
+ \let\forestmathresulttype\forest at process@result at type
+ }{%
+ \forestmathparse@{#1}%
+ \def\forestmathresulttype{P}%
+ }%
+}
+\def\forestmathparse@#1{%
+ \forest at isdim{#1}{%
+ \edef\forestmathresult{\expandafter\Pgf at geT\the\forest at isdim@dimen}%
+ }{%
+ \pgfmathsetmacro\forestmathresult{#1}%
+ }%
+}
+% \end{macrocode}
+% Evaluates |#1| to a boolean: if true execute |#2|, otherwise |#3|. |#2| and |#3| are \TeX\ code.
+% Includes a shortcut for some common values.
+% \begin{macrocode}
+\csdef{forest at bh@0}{0}
+\csdef{forest at bh@false}{0}
+\csdef{forest at bh@1}{1}
+\csdef{forest at bh@true}{1}
+\def\forestmath at if#1{%
+ \ifcsdef{forest at bh@\detokenize{#1}}{%
+ \let\forest at next\forestmath at if@fast
+ }{%
+ \let\forest at next\forestmath at if@slow
+ }%
+ \forest at next{#1}%
+ \ifnum\forest at temp=0
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+}
+\def\forestmath at if@fast#1{\letcs\forest at temp{forest at bh@\detokenize{#1}}}
+\def\forestmath at if@slow#1{\forestmathtruncatemacro\forest at temp{#1}}
+% \end{macrocode}
+% These macros expandably convert a num(n)/dim(d)/unitless dim(P) to a num(n)/dim(d)/unitless
+% dim(P).
+% \begin{macrocode}
+\def\forestmath at convert@fromto#1#2#3{%
+ \edef\forestmathresult{\csname forestmath at convert@from@#1 at to@#2\endcsname{#3}}}
+\def\forestmath at convert@from#1{\forestmath at convert@fromto{#1}{\forestmathresulttype}}
+\def\forestmath at convert@to{\forestmath at convert@fromto{\forestmathresulttype}}
+\def\forestmath at convert@from at n@to at n#1{#1}
+\def\forestmath at convert@from at n@to at d#1{#1\pgfmath at pt}
+\def\forestmath at convert@from at n@to at P#1{#1}
+\def\forestmath at convert@from at d@to at n#1{%
+ \expandafter\forestmath at convert@uptodot\Pgf at geT#1.\forest at eov}
+\def\forestmath at convert@from at d@to at d#1{#1}
+\def\forestmath at convert@from at d@to at P#1{\Pgf at geT#1}
+\def\forestmath at convert@from at P@to at n#1{%
+ \forestmath at convert@uptodot#1.\forest at eov}
+\def\forestmath at convert@from at P@to at d#1{#1\pgfmath at pt}
+\def\forestmath at convert@from at P@to at P#1{#1}
+\def\forestmath at convert@uptodot#1.#2\forest at eov{#1}
+\def\forestmathzero{\forestmath at convert@from\forestmathtype at count{0}}
+% \end{macrocode}
+% These defer conversion (see aggregates).
+% \begin{macrocode}
+\csdef{forestmath at convert@from at n@to at _}#1{\unexpanded{#1}}
+\csdef{forestmath at convert@from at d@to at _}#1{\unexpanded{#1}}
+\csdef{forestmath at convert@from at P@to at _}#1{\unexpanded{#1}}
+% \end{macrocode}
+% Sets |\pgfmathresulttype| to the type of |#1|.
+% \begin{macrocode}
+\def\forestmathsettypefrom#1{%
+ \forest at isnumdim{%
+ \let\forestmathresulttype\forest at result@type at numexpr
+ }{%
+ \let\forestmathresulttype\forest at result@type at dimexpr
+ }{%
+ \let\forestmathresulttype\forest at result@type at pgfmath
+ }%
+}
+% \end{macrocode}
+% The following functions expect numbers or (bare or specified) dimensions as their parameters. The
+% version ending in |@| should get the argument type as its first argument; the version without |@|
+% uses |\forestmathresulttype|. The result type doesn't need to be changed, obviously.
+% \begin{macrocode}
+\def\forestmathadd#1#2{\edef\forestmathresult{%
+ \csname forestmathadd@\forestmathresulttype\endcsname{#1}{#2}}}
+\def\forestmathadd@#1#2#3{\edef\forestmathresult{%
+ \csname forestmathadd@#1\endcsname{#2}{#3}}}
+\def\forestmathadd at n#1#2{\the\numexpr#1+#2\relax}
+\def\forestmathadd at d#1#2{\the\dimexpr#1+#2\relax}
+\def\forestmathadd at P#1#2{\expandafter\Pgf at geT\the\dimexpr#1pt+#2pt\relax}
+\def\forestmathmultiply#1#2{%
+ \csname forestmathmultiply@\forestmathresulttype\endcsname{#1}{#2}}
+\def\forestmathmultiply@#1#2#3{%
+ \csname forestmathmultiply@#1\endcsname{#2}{#3}}
+\def\forestmathmultiply at n#1#2{\edef\forestmathresult{%
+ \the\numexpr#1*#2\relax}}
+\def\forestmathmultiply at d#1#2{%
+ \edef\forestmath at marshal{\forestmathmultiply at d@{#1}{#2}}\forestmath at marshal
+}
+\def\forestmathmultiply at d@#1#2{%
+ \edef\forestmath at marshal{%
+ \noexpand\pgfmathmultiply@{\Pgf at geT#1}{\Pgf at geT#2}%
+ }\forestmath at marshal
+ \edef\forestmathresult{\pgfmathresult\pgfmath at pt}%
+}
+\def\forestmathmultiply at P#1#2{%
+ \pgfmathmultiply@{#1}{#2}%
+ \let\forestmathresult\pgfmathresult
+}
+% \end{macrocode}
+% The return type of |forestmathdivide| is the type of the dividend. So, |n| and |d| type can only
+% be divided by integers; as |\numexpr| and |\dimexpr| are used, the result is rounded.
+% \begin{macrocode}
+\def\forestmathdivide#1#2{%
+ \csname forestmathdivide@\forestmathresulttype\endcsname{#1}{#2}}
+\def\forestmathdivide@#1#2#3{%
+ \csname forestmathdivide@#1\endcsname{#2}{#3}}
+\def\forestmathdivide at n#1#2{\edef\forestmathresult{%
+ \the\numexpr#1/#2\relax}}
+\def\forestmathdivide at d#1#2{\edef\forestmathresult{%
+ \the\dimexpr#1/#2\relax}}
+\def\forestmathdivide at P#1#2{%
+ \edef\forest at marshal{%
+ \noexpand\pgfmathdivide{+#1}{+#2}%
+ }\forest at marshal
+ \let\forestmathresult\pgfmathresult
+}
+% \end{macrocode}
+% Booleans.
+% \begin{macrocode}
+\def\forestmathtrue{%
+ \def\forestmathresult{1}%
+ \let\forestmathresulttype\forestmathtype at count}
+\def\forestmathfalse{%
+ \def\forestmathresult{0}%
+ \let\forestmathresulttype\forestmathtype at count}
+% \end{macrocode}
+% Comparisons. |\pdfstrcmp| is used to compare text (types |t| and |T|); note that it expands its
+% arguments. |<| and |>| comparison of generic type obviously makes no sense; |=| comparison is
+% done using |\ifx|: this is also the reason why these macros are not fully expandable, as we need
+% to |\def| the arguments to |\ifx|.
+%
+% Low level |<|.
+% \begin{macrocode}
+\def\forestmath at if@lt at n#1#2{\ifnum#1<#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at d#1#2{\ifdim#1<#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at P#1#2{\ifdim#1pt<#2pt
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at t#1#2{\ifnum\pdfstrcmp{#1}{#2}<0
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at T#1#2{\ifnum\pdfstrcmp{#1}{#2}>0
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forest at cmp@error#1#2{\PackageError{forest}{Comparison
+ ("<" or ">") of generic type arguments "#1" and "#2"
+ makes no sense}{Use one of argument processor instructions
+ "n", "d", "P" or "t" to change the type. Use package option
+ "debug=process" to see what's happening here.}}
+\cslet{forestmath at if@lt at _}\forest at cmp@error
+% \end{macrocode}
+% Low level |=|.
+% \begin{macrocode}
+\def\forestmath at if@eq at n#1#2{\ifnum#1=#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@eq at d#1#2{\ifdim#1=#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@eq at P#1#2{\ifdim#1pt=#2pt
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@eq at t#1#2{\ifnum\pdfstrcmp{#1}{#2}=0
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\let\forestmath at if@eq at T\forestmath at if@eq at t
+\csdef{forestmath at if@eq at _}#1#2{%
+ \def\forestmath at tempa{#1}%
+ \def\forestmath at tempb{#2}%
+ \ifx\forestmath at tempa\forestmath at tempb
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+% \end{macrocode}
+% High level |<|, |>| and |=|.
+% \begin{macrocode}
+\def\forestmathlt#1#2{%
+ \csname forestmath at if@lt@\forestmathresulttype\endcsname{#1}{#2}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathlt@#1#2#3{%
+ \csname forestmath at if@lt@#1\endcsname{#2}{#3}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathgt#1#2{%
+ \csname forestmath at if@lt@\forestmathresulttype\endcsname{#2}{#1}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathgt@#1#2#3{%
+ \csname forestmath at if@lt@#1\endcsname{#3}{#2}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmatheq#1#2{%
+ \csname forestmath at if@eq@\forestmathresulttype\endcsname{#1}{#2}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmatheq@#1#2#3{%
+ \csname forestmath at if@eq@#1\endcsname{#2}{#3}%
+ \forestmathtrue
+ \forestmathfalse}
+% \end{macrocode}
+% Min and max. The complication here is that for numeric/dimension types, we want the empty value to
+% signal ``no argument'', i.e.\ the other argument should be the result; this is used in
+% aggregates. (For text types, the empty value is obviously the lesser one.) The arguments are expanded.
+% \begin{macrocode}
+\def\forestmathmin{\forestmath at minmax{min}{\forestmathresulttype}}
+\def\forestmathmax{\forestmath at minmax{max}{\forestmathresulttype}}
+\def\forestmathmin@{\forestmath at minmax{min}}
+\def\forestmathmax@{\forestmath at minmax{max}}
+\def\forestmath at minmax#1#2#3#4{% #1=min/max, #2=type, #3,#4=args
+ \edef\forestmath at tempa{#3}%
+ \edef\forestmath at tempb{#4}%
+ \if\relax\detokenize\expandafter{\forestmath at tempa}\relax
+ \forestmath at minmax@one{#1}{#2}\forestmath at tempb
+ \else
+ \if\relax\detokenize\expandafter{\forestmath at tempb}\relax
+ \forestmath at minmax@one{#1}{#2}\forestmath at tempa
+ \else
+ \csname forestmath@#1\endcsname{#2}%
+ \fi
+ \fi
+}
+\def\forestmath at minmax@one#1#2#3{% #1=min/max, #2=type, #3 = the (possibly) non-empty arg
+ \ifcsname forestmath@#1 at one@#2\endcsname
+ \csname forestmath@#1 at one@#2\endcsname#3%
+ \else
+ \let\forestmathresult#3%
+ \fi
+}
+\def\forestmath at min@one at t#1{\let\forestmathresult\forest at empty}
+\def\forestmath at max@one at t#1{\let\forestmathresult#1}
+\def\forestmath at min@one at T#1{\let\forestmathresult#1}
+\def\forestmath at max@one at T#1{\let\forestmathresult\forest at empty}
+
+\def\forestmath at min#1{% #1 = type
+ \csname forestmath at if@lt@#1\endcsname\forestmath at tempa\forestmath at tempb
+ {\let\forestmathresult\forestmath at tempa}%
+ {\let\forestmathresult\forestmath at tempb}%
+}
+\def\forestmath at max#1{% #1 = type
+ \csname forestmath at if@lt@#1\endcsname\forestmath at tempa\forestmath at tempb
+ {\let\forestmathresult\forestmath at tempb}%
+ {\let\forestmathresult\forestmath at tempa}%
+}
+% \end{macrocode}
+%
% \subsection{Sorting}
%
% Macro |\forest at sort| is the user interface to sorting.
@@ -1258,30 +2204,29 @@
% Macros for retrieving/setting node options of the current node.
% \begin{macrocode}
% full expansion expands precisely to the value
-\def\forestov#1{\expandafter\expandafter\expandafter\expandonce
- \pgfkeysvalueof{/forest/@node/\forest at cn/#1}}
+\def\forestov#1{\expandafter\expandonce\csname fRsT\forest at cn/#1\endcsname}
% full expansion expands all the way
-\def\forestove#1{\pgfkeysvalueof{/forest/@node/\forest at cn/#1}}
+\def\forestove#1{\csname fRsT\forest at cn/#1\endcsname}
% full expansion expands to the cs holding the value
-\def\forestom#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/\forest at cn/#1}}}
-\def\forestoget#1#2{\pgfkeysgetvalue{/forest/@node/\forest at cn/#1}{#2}}
-\def\forestolet#1#2{\pgfkeyslet{/forest/@node/\forest at cn/#1}{#2}}
-\def\forestocslet#1#2{%
- \edef\forest at marshal{%
- \noexpand\pgfkeyslet{/forest/@node/\forest at cn/#1}{\expandonce{\csname#2\endcsname}}%
- }\forest at marshal
-}
-\def\forestoset#1#2{\pgfkeyssetvalue{/forest/@node/\forest at cn/#1}{#2}}
-\def\forestoeset#1#2{%
- \edef\forest at option@temp{%
- \noexpand\pgfkeyssetvalue{/forest/@node/\forest at cn/#1}{#2}%
- }\forest at option@temp
-}
+\def\forestom#1{\expandonce{\csname fRsT\forest at cn/#1\endcsname}}
+\def\forestoget#1#2{\expandafter\let\expandafter#2\csname fRsT\forest at cn/#1\endcsname}
+\def\forestolet#1#2{\expandafter\let\csname fRsT\forest at cn/#1\endcsname#2}
+% \def\forestocslet#1#2{%
+% \edef\forest at marshal{%
+% \noexpand\pgfkeyslet{/forest/@node/\forest at cn/#1}{\expandonce{\csname#2\endcsname}}%
+% }\forest at marshal
+% }
+\def\forestoset#1#2{\expandafter\edef\csname fRsT\forest at cn/#1\endcsname{\unexpanded{#2}}}
+\def\forestoeset#1%#2
+ {\expandafter\edef\csname fRsT\forest at cn/#1\endcsname
+ %{#2}
+ }
\def\forestoappto#1#2{%
\forestoeset{#1}{\forestov{#1}\unexpanded{#2}}%
}
-\def\forestoifdefined#1#2#3{%
- \pgfkeysifdefined{/forest/@node/\forest at cn/#1}{#2}{#3}%
+\def\forestoifdefined#1%#2#3
+{%
+ \ifcsdef{fRsT\forest at cn/#1}%{#2}{#3}%
}
% \end{macrocode}
% User macros for retrieving node options of the current node.
@@ -1291,25 +2236,22 @@
% \end{macrocode}
% Macros for retrieving node options of a node given by its id.
% \begin{macrocode}
-\def\forestOv#1#2{\expandafter\expandafter\expandafter\expandonce
- \pgfkeysvalueof{/forest/@node/#1/#2}}
-\def\forestOve#1#2{\pgfkeysvalueof{/forest/@node/#1/#2}}
+\def\forestOv#1#2{\expandafter\expandonce\csname fRsT#1/#2\endcsname}
+\def\forestOve#1#2{\csname fRsT#1/#2\endcsname}
% full expansion expands to the cs holding the value
-\def\forestOm#1#2{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/#1/#2}}}
-\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}}
-\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}}
-\def\forestOlet#1#2#3{\pgfkeyslet{/forest/@node/#1/#2}{#3}}
-\def\forestOcslet#1#2#3{%
- \edef\forest at marshal{%
- \noexpand\pgfkeyslet{/forest/@node/#1/#2}{\expandonce{\csname#3\endcsname}}%
- }\forest at marshal
+\def\forestOm#1#2{\expandonce{\csname fRsT#1/#2\endcsname}}
+\def\forestOget#1#2#3{\expandafter\let\expandafter#3\csname fRsT#1/#2\endcsname}
+\def\forestOlet#1#2#3{\expandafter\let\csname fRsT#1/#2\endcsname#3}
+% \def\forestOcslet#1#2#3{%
+% \edef\forest at marshal{%
+% \noexpand\pgfkeyslet{/forest/@node/#1/#2}{\expandonce{\csname#3\endcsname}}%
+% }\forest at marshal
+% }
+\def\forestOset#1#2#3{\expandafter\edef\csname fRsT#1/#2\endcsname{\unexpanded{#3}}}
+\def\forestOeset#1#2%#3
+{\expandafter\edef\csname fRsT#1/#2\endcsname
+ % {#3}
}
-\def\forestOset#1#2#3{\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}}
-\def\forestOeset#1#2#3{%
- \edef\forestoption at temp{%
- \noexpand\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}%
- }\forestoption at temp
-}
\def\forestOappto#1#2#3{%
\forestOeset{#1}{#2}{\forestOv{#1}{#2}\unexpanded{#3}}%
}
@@ -1322,8 +2264,9 @@
\def\forestOepreto#1#2#3{%
\forestOeset{#1}{#2}{#3\forestOv{#1}{#2}}%
}
-\def\forestOifdefined#1#2#3#4{%
- \pgfkeysifdefined{/forest/@node/#1/#2}{#3}{#4}%
+\def\forestOifdefined#1#2%#3#4
+{%
+ \ifcsdef{fRsT#1/#2}%{#3}{#4}%
}
\def\forestOletO#1#2#3#4{% option #2 of node #1 <-- option #4 of node #3
\forestOget{#3}{#4}\forestoption at temp
@@ -1338,28 +2281,58 @@
\forestoget{#2}\forestoption at temp
\forestolet{#1}\forestoption at temp}
% \end{macrocode}
+% Macros for retrieving node options given by \meta{relative node name}|.|\meta{option}.
+% \begin{macrocode}
+\def\forestRNOget#1#2{% #1=rn!option, #2 = receiving cs
+ \pgfutil at in@{.}{#1}%
+ \ifpgfutil at in@
+ \forestRNOget at rn#2#1\forest at END
+ \else
+ \forestoget{#1}#2%
+ \fi
+}
+\def\forestRNOget at rn#1#2.#3\forest at END{%
+ \forest at forthis{%
+ \forest at nameandgo{#2}%
+ \forestoget{#3}#1%
+ }%
+}
+\def\forestRNO at getvalueandtype#1#2#3{% #1=rn.option, #2,#3 = receiving css
+ \pgfutil at in@{.}{#1}%
+ \ifpgfutil at in@
+ \forestRNO at getvalueandtype@rn#2#3#1\forest at END
+ \else
+ \forestoget{#1}#2%
+ \pgfkeysgetvalue{/forest/#1/@type}#3%
+ \fi
+}
+\def\forestRNO at getvalueandtype@rn#1#2#3.#4\forest at END{%
+ % #1,#2=receiving css, #3=relative node name, #4=option name
+ \forest at forthis{%
+ \forest at nameandgo{#3}%
+ \forestoget{#4}#1%
+ }%
+ \pgfkeysgetvalue{/forest/#4/@type}#2%
+}
+% \end{macrocode}
% Macros for retrieving/setting registers.
% \begin{macrocode}
% full expansion expands precisely to the value
-\def\forestrv#1{\expandafter\expandafter\expandafter\expandonce
- \pgfkeysvalueof{/forest/@node/register/#1}}
+\def\forestrv#1{\expandafter\expandonce\csname fRsT/#1\endcsname}
% full expansion expands all the way
-\def\forestrve#1{\pgfkeysvalueof{/forest/@node/register/#1}}
+\def\forestrve#1{\csname fRsT/#1\endcsname}
% full expansion expands to the cs holding the value
-\def\forestrm#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/register/#1}}}
-\def\forestrget#1#2{\pgfkeysgetvalue{/forest/@node/register/#1}{#2}}
-\def\forestrlet#1#2{\pgfkeyslet{/forest/@node/register/#1}{#2}}
-\def\forestrcslet#1#2{%
- \edef\forest at marshal{%
- \noexpand\pgfkeyslet{/forest/@node/register/#1}{\expandonce{\csname#2\endcsname}}%
- }\forest at marshal
-}
-\def\forestrset#1#2{\pgfkeyssetvalue{/forest/@node/register/#1}{#2}}
-\def\forestreset#1#2{%
- \edef\forest at option@temp{%
- \noexpand\pgfkeyssetvalue{/forest/@node/register/#1}{#2}%
- }\forest at option@temp
-}
+\def\forestrm#1{\expandonce{\csname fRsT/#1\endcsname}}
+\def\forestrget#1#2{\expandafter\let\expandafter#2\csname fRsT/#1\endcsname}
+\def\forestrlet#1#2{\expandafter\let\csname fRsT/#1\endcsname#2}
+% \def\forestrcslet#1#2{%
+% \edef\forest at marshal{%
+% \noexpand\pgfkeyslet{/forest/@node/register/#1}{\expandonce{\csname#2\endcsname}}%
+% }\forest at marshal
+% }
+\def\forestrset#1#2{\expandafter\edef\csname fRsT/#1\endcsname{\unexpanded{#2}}}
+\def\forestreset#1%#2
+ {\expandafter\edef\csname fRsT/#1\endcsname}%{#2}
\def\forestrappto#1#2{%
\forestreset{#1}{\forestrv{#1}\unexpanded{#2}}%
}
@@ -1366,8 +2339,9 @@
\def\forestrpreto#1#2{%
\forestreset{#1}{\unexpanded{#2}\forestrv{#1}}%
}
-\def\forestrifdefined#1#2#3{%
- \pgfkeysifdefined{/forest/@node/register/#1}{#2}{#3}%
+\def\forestrifdefined#1%#2#3
+{%
+ \ifcsdef{fRsT/#1}%{#2}{#3}%
}
% \end{macrocode}
% User macros for retrieving node options of the current node.
@@ -1946,7 +2920,12 @@
% \begin{macrocode}
\NewDocumentCommand\forestdebugtypeouttrees{o}{%
\forestdebug at typeouttrees\forest at temp
- \typeout{\IfValueTF{#1}{#1: }{}\forest at temp}%
+ \typeout{%
+ \forestdebugtypeouttreesprefix
+ \IfValueTF{#1}{#1: }{}%
+ \detokenize\expandafter{\forest at temp}%
+ \forestdebugtypeouttreessuffix
+ }%
}
\def\forestdebug at typeouttrees#1{% #1 = cs to store the result
\begingroup
@@ -1968,12 +2947,12 @@
\expandafter\endgroup
\expandafter\edef\expandafter\forest at cn\expandafter{\forest at cn}%
\forestdebug at typeouttree@build
- \appto\forest at temp@message{\space}%
+ \appto\forest at temp@message{ }%
}%
}%
\repeat
\expandafter\endgroup
- \expandafter\edef\expandafter#1\expandafter{\forest at temp@message}%
+ \expandafter\def\expandafter#1\expandafter{\forest at temp@message}%
}
\def\forestdebug at typeouttrees@findroot{%
\let\forestdebug at typeouttrees@next\relax
@@ -2003,9 +2982,9 @@
% Recurse through the tree. If a circularity is detected, mark it with |*| and stop recursion.
% \begin{macrocode}
\def\forestdebug at typeouttree@build{%
- \eappto\forest at temp@message{[\forest at cn%]
+ \eappto\forest at temp@message{[\forestdebugtypeouttreenodeinfo%]
\ifcsdef{forestdebug at typeouttree@used@\forest at cn}{*}{}%
- }%
+ }%
\ifcsdef{forestdebug at typeouttree@used@\forest at cn}{}{%
\csdef{forestdebug at typeouttree@used@\forest at cn}{}%
\forest at node@foreachchild{\forestdebug at typeouttree@build}%
@@ -2013,6 +2992,9 @@
\eappto\forest at temp@message{%[
]}%
}
+\def\forestdebugtypeouttreenodeinfo{\forest at cn}
+\def\forestdebugtypeouttreesprefix{}
+\def\forestdebugtypeouttreessuffix{}
% \end{macrocode}
%
%
@@ -2104,6 +3086,7 @@
\pgfkeyssetvalue{#1/option at name}{#3}%
\pgfkeyssetvalue{#1+/option at name}{#3}%
\pgfkeyssetvalue{#2/+#3/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at generic % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at toks{##1}{#3}}%
}
\def\forest at declareautowrappedtoks@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix
@@ -2133,8 +3116,27 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}},
+ #2/where #3</.style n args={3}{for tree={#2/if #3<={##1}{##2}{##3}}},
+ #2/where #3>/.style n args={3}{for tree={#2/if #3>={##1}{##2}{##3}}},
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at dimen % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at dimen{##1}{#3}}%
}
\def\forest at declaredimen@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -2141,17 +3143,17 @@
\forest at declarereadonlydimen@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{%
#1/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\forestOlet{\forest at setter@node}{#3}\forest at temp
},
#1+/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestove{#3}
\advance\pgfutil at tempdima\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\pgfutil at tempdima}%
},
#1-/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestove{#3}
\advance\pgfutil at tempdima-\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\pgfutil at tempdima}%
@@ -2208,8 +3210,27 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}},
+ #2/where #3</.style n args={3}{for tree={#2/if #3<={##1}{##2}{##3}}},
+ #2/where #3>/.style n args={3}{for tree={#2/if #3>={##1}{##2}{##3}}},
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at count{##1}{#3}}%
}
\def\forest at declarecount@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -2216,29 +3237,29 @@
\forest at declarereadonlycount@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{
#1/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\forestOlet{\forest at setter@node}{#3}\forest at temp
},
#1+/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\advance\c at pgf@counta\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
},
#1-/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\advance\c at pgf@counta-\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
},
#1*/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\multiply\c at pgf@counta\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
},
#1:/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\divide\c at pgf@counta\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
@@ -2279,33 +3300,33 @@
\pgfkeyssetvalue{#1'*/option at name}{#3}%
\pgfkeyssetvalue{#1':/option at name}{#3}%
}
+% \end{macrocode}
+% Nothing else should be defined in this namespace.
+% \begin{macrocode}
\def\forest at declareboolean@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
\pgfkeysalso{%
#1/.code={%
- \ifstrequal{##1}{1}{%
- \forestOset{\forest at setter@node}{#3}{1}%
+ \forestmath at if{##1}{%
+ \def\forest at temp{1}%
}{%
- \ifstrequal{##1}{0}{%
- \forestOset{\forest at setter@node}{#3}{0}%
- }{%
- \pgfmathifthenelse{##1}{1}{0}%
- \forestOlet{\forest at setter@node}{#3}\pgfmathresult
- }%
+ \def\forest at temp{0}%
}%
+ \forestOlet{\forest at setter@node}{#3}\forest at temp
},
#1/.default=1,
#2/not #3/.code={\forestOset{\forest at setter@node}{#3}{0}},
#2/if #3/.code 2 args={%
\forestoget{#3}\forest at temp@option at value
- \ifnum\forest at temp@option at value=1
+ \ifnum\forest at temp@option at value=0
+ \pgfkeysalso{##2}%
+ \else
\pgfkeysalso{##1}%
- \else
- \pgfkeysalso{##2}%
\fi
},
#2/where #3/.style 2 args={for tree={#2/if #3={##1}{##2}}}
}%
\pgfkeyssetvalue{#1/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at count{##1}{#3}}%
}
\forestset{
@@ -2319,35 +3340,44 @@
\forest at declarehandler\forest at declarekeylist@handler{#1}{#2}%
},
declare readonly dimen/.code 2 args={%
- \pgfmathsetlengthmacro\forest at temp{#2}%
+ \forestmathsetlengthmacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declarereadonlydimen@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare dimen/.code 2 args={%
- \pgfmathsetlengthmacro\forest at temp{#2}%
+ \forestmathsetlengthmacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declaredimen@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare readonly count/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#2}%
+ \forestmathtruncatemacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declarereadonlycount@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare count/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#2}%
+ \forestmathtruncatemacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declarecount@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare boolean/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#2}%
+ \forestmath at if{#2}{%
+ \def\forest at temp{1}%
+ }{%
+ \def\forest at temp{0}%
+ }%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declareboolean@handler{#1}}{\forest at temp}%
}\forest at marshal
},
+% \end{macrocode}
+%
+% \section{Handlers}
+%
+% \begin{macrocode}
/handlers/.restore default value/.code={%
\edef\forest at handlers@currentpath{\pgfkeyscurrentpath}%
\pgfkeysgetvalue{\pgfkeyscurrentpath/option at name}\forest at currentoptionname
@@ -2367,10 +3397,15 @@
\pgfkeysalso{\forest at handlers@wrap at currentpath/.expand once=\forest at wrapped@value}%
},
/handlers/.option/.code={%
- \edef\forest at marshal{%
- \noexpand\pgfkeysalso{\pgfkeyscurrentpath={\forestoption{#1}}}%
- }\forest at marshal
+ \edef\forest at temp{\pgfkeyscurrentpath}%
+ \expandafter\forest at handlers@option\expandafter{\forest at temp}{#1}%
},
+}
+\def\forest at handlers@option#1#2{%#1=pgfkeyscurrentpath,#2=relative node name
+ \forestRNOget{#2}\forest at temp
+ \pgfkeysalso{#1/.expand once={\forest at temp}}%
+}%
+\forestset{
/handlers/.register/.code={%
\edef\forest at marshal{%
\noexpand\pgfkeysalso{\pgfkeyscurrentpath={\forestregister{#1}}}%
@@ -2377,7 +3412,7 @@
}\forest at marshal
},
/handlers/.wrap pgfmath arg/.code 2 args={%
- \pgfmathparse{#2}\let\forest at wrap@arg at i\pgfmathresult
+ \forestmathparse{#2}\let\forest at wrap@arg at i\forestmathresult
\edef\forest at wrap@args{{\expandonce\forest at wrap@arg at i}}%
\def\forest at wrap@code##1{#1}%
% here we don't call \forest at wrap@pgfmath at args@@@wrapandpasson, as compat-2.0.2-wrappgfmathargs changes that to achieve the old, confusing state of affairs, which *didn't* apply at *1*-arg pgfmath wrapping
@@ -2385,8 +3420,8 @@
\expandafter\pgfkeysalso\expandafter{\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{\the\forest at temp@toks}}%
},
/handlers/.wrap 2 pgfmath args/.code n args={3}{%
- \pgfmathparse{#2}\let\forest at wrap@arg at i\pgfmathresult
- \pgfmathparse{#3}\let\forest at wrap@arg at ii\pgfmathresult
+ \forestmathparse{#2}\let\forest at wrap@arg at i\forestmathresult
+ \forestmathparse{#3}\let\forest at wrap@arg at ii\forestmathresult
\edef\forest at wrap@args{{\expandonce\forest at wrap@arg at i}{\expandonce\forest at wrap@arg at ii}}%
\def\forest at wrap@code##1##2{#1}%
\forest at wrap@pgfmath at args@@@wrapandpasson
@@ -2409,19 +3444,16 @@
/handlers/.wrap 8 pgfmath args/.code n args={9}{%
\forest at wrap@n at pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}{8}%
\forest at wrap@n at pgfmath@do{#1}{8}},
- /handlers/.process args/.code={%
- \forest at processargs#1\forest at eov\forest at END
- },
}
\def\forest at wrap@n at pgfmath@args#1#2#3#4#5#6#7#8#9{%
- \pgfmathparse{#1}\let\forest at wrap@arg at i\pgfmathresult
- \ifnum#9>1 \pgfmathparse{#2}\let\forest at wrap@arg at ii\pgfmathresult\fi
- \ifnum#9>2 \pgfmathparse{#3}\let\forest at wrap@arg at iii\pgfmathresult\fi
- \ifnum#9>3 \pgfmathparse{#4}\let\forest at wrap@arg at iv\pgfmathresult\fi
- \ifnum#9>4 \pgfmathparse{#5}\let\forest at wrap@arg at v\pgfmathresult\fi
- \ifnum#9>5 \pgfmathparse{#6}\let\forest at wrap@arg at vi\pgfmathresult\fi
- \ifnum#9>6 \pgfmathparse{#7}\let\forest at wrap@arg at vii\pgfmathresult\fi
- \ifnum#9>7 \pgfmathparse{#8}\let\forest at wrap@arg at viii\pgfmathresult\fi
+ \forestmathparse{#1}\let\forest at wrap@arg at i\forestmathresult
+ \ifnum#9>1 \forestmathparse{#2}\let\forest at wrap@arg at ii\forestmathresult\fi
+ \ifnum#9>2 \forestmathparse{#3}\let\forest at wrap@arg at iii\forestmathresult\fi
+ \ifnum#9>3 \forestmathparse{#4}\let\forest at wrap@arg at iv\forestmathresult\fi
+ \ifnum#9>4 \forestmathparse{#5}\let\forest at wrap@arg at v\forestmathresult\fi
+ \ifnum#9>5 \forestmathparse{#6}\let\forest at wrap@arg at vi\forestmathresult\fi
+ \ifnum#9>6 \forestmathparse{#7}\let\forest at wrap@arg at vii\forestmathresult\fi
+ \ifnum#9>7 \forestmathparse{#8}\let\forest at wrap@arg at viii\forestmathresult\fi
\edef\forest at wrap@args{%
{\expandonce\forest at wrap@arg at i}
\ifnum#9>1 {\expandonce\forest at wrap@arg at ii}\fi
@@ -2457,103 +3489,541 @@
\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{%
\the\forest at temp@toks}}%
}
-\newtoks\forest at processargs@result
-\newtoks\forest at processargs@current
-\newif\ifforest at processargs@append
-\def\forest at eov{\forest at eov}
-\def\forest at processargs#1#2\forest at END{% #1 = processing instructions, #2 = args
- \forest at processargs@result{}%
- \forest at processargs@current{}%
- \forest at processargs@appendfalse
- \forest at processargs@getins#1.\forest at END#2\forest at END
+% \end{macrocode}
+%
+% \subsection{.process}
+%
+% \begin{macrocode}
+\def\forest at process@catregime{} % filled by processor defs
+\forest at newarray\forest at process@left@ % processed args
+\forest at newarray\forest at process@right@ % unprocessed args
+\forest at newarray\forest at process@saved@ % used by instructions |S| and |U|
+\let\forest at process@savedtype\forestmathtype at none
+\forest at newglobalarray\forest at process@result@
+\newif\ifforest at process@returnarray@
+% \end{macrocode}
+% Processing instruction need not (but may) be enclosed in braces.
+% \begin{macrocode}
+\def\forest at process#1#2#{% #1 = true/false (should we return an array?)
+ % #2 = processing instructions (if non-empty),
+ % (initial) args follow
+ \ifblank{#2}{\forest at process@a{#1}}{\forest at process@a{#1}{#2}}%
}
-\def\forest at processargs@maybeappend{%
- \ifforest at processargs@append
- \eapptotoks\forest at processargs@result{{\the\forest at processargs@current}}%
- \forest at processargs@current{}%
- \fi
+\Inline\def\forest at process@a#1#2{%
+ \begingroup
+ \forest at process@left at clear
+ \forest at process@right at clear
+ \forest at process@saved at clear
+ \let\forest at process@savedtype\forestmathtype at generic
+ \ExpandIfT{forestdebug}{%
+ \edef\forest at process@debug at args{\unexpanded{#2}}%
+ \typeout{[forest .process] Start "\unexpanded{#2}"}%
+ }%
+ \csname forest at process@returnarray@#1\endcsname
+ \def\forest at topextend@next{%
+ \forest at process@catregime
+ \endlinechar=-1
+ \scantokens{#2}%
+ \forest at process@finish
+ }%
+ \forest at process@right at topextend
}
-\def\forest at processargs@getins#1#2\forest at END#3\forest at END{% #1 = first instruction, #2 = rest of instructions, #3 = args
- \csname forest at processargs@ins@#1\endcsname#2\forest at END#3\forest at END
+\pgfkeys{%
+ /handlers/.process/.code={%
+ \forest at process{true}#1\forest at eov
+ \edef\forest at marshal{%
+ \noexpand\pgfkeysalso{\noexpand\pgfkeyscurrentpath=\forest at process@result at values}%
+ }\forest at marshal
+ },
+ /forest/copy command key={/handlers/.process}{/handlers/.process args},
}
-\csdef{forest at processargs@ins at .}\forest at END#1\forest at END{%
- \forest at processargs@maybeappend
- \forest at processargs@appremainingargs#1\forest at END
+\def\forest at process@finish{%
+ \ifforest at process@returnarray@
+ \forest at process@finish at array
+ \global\let\forest at process@result at type\forest at result@type at array
+ \else
+ \forest at process@finish at single
+ \fi
+ \ifforestdebugprocess\forest at process@debug at end\fi
+ \endgroup
}
-\def\forest at processargs@appremainingargs#1#2\forest at END{%
- \edef\forest at temp{\unexpanded{#1}}%
- \ifx\forest at temp\forest at eov
- \let\forest at processargs@next\forest at processargs@done
+\def\forest at process@finish at single{%
+ \edef\forest at temp{forest at process@finish at single@%
+ \the\numexpr\forest at process@left at N-\forest at process@left at M\relax
+ \the\numexpr\forest at process@right at N-\forest at process@right at M\relax
+ }%
+ \ifcsname\forest at temp\endcsname
+ \csname\forest at temp\endcsname
+ \global\let\forest at process@result\forest at temp
\else
- \apptotoks\forest at processargs@result{{#1}}%
- \let\forest at processargs@next\forest at processargs@appremainingargs
+ \forest at process@lengtherror
\fi
- \forest at processargs@next#2\forest at END
+ \global\let\forest at process@result at type\forestmathresulttype
}
-\def\forest at processargs@done#1\forest at END{%
- \pgfkeysalso{\pgfkeyscurrentpath/.expanded=\the\forest at processargs@result}%
+\csdef{forest at process@finish at single@10}{\forest at process@left at toppop\forest at temp}
+\csdef{forest at process@finish at single@01}{\forest at process@right at toppop\forest at temp}
+\def\forest at process@finish at array{%
+ \forest at process@result at clear
+ \forest at temp@count\forest at process@left at M\relax
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@left at N\relax
+ \forest at process@left at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@result at letappend\forest at temp
+ \advance\forest at temp@count1
+ \forest at repeat
+ \forest at temp@count\forest at process@right at M\relax
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@right at N\relax
+ \forest at process@right at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@result at letappend\forest at temp
+ \advance\forest at temp@count1
+ \forest at repeat
}
-\csdef{forest at processargs@ins at _}#1\forest at END#2#3\forest at END{% no processing
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \forest at processargs@current{#2}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+% \end{macrocode}
+% Debugging and error messages.
+% \begin{macrocode}
+\ifforestdebug
+ \let\forest at process@d\forest at process@b
+ \def\forest at process@b#1\forest at eov{% save and print initial arguments
+ \edef\forest at process@debug at args{\unexpanded{#1}}%
+ \typeout{[forest .process] Start "\unexpanded{#1}"}%
+ \forest at process@d#1\forest at eov
+ }
+\fi
+\def\forest at process@debug at end{%
+ \typeout{[forest .process] \space\space\space End "\expandonce{\forest at process@debug at args}" -> "\forest at process@left at values\forest at process@right at values"}%
}
-\csdef{forest at processargs@ins at x}#1\forest at END#2#3\forest at END{% expand
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \etotoks\forest at processargs@current{#2}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at process@lengtherror{%
+ \PackageError{forest}{%
+ The ".process" expression was expected to evaluate to a single argument,
+ but the result is \the\forest at process@result at N
+ \space items long.}{}%
}
-\csdef{forest at processargs@ins at o}#1\forest at END#2#3\forest at END{% expand once
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \expandafter\forest at processargs@current\expandafter{#2}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+% \end{macrocode}
+% Define the definer of processors. First, deal with the catcode of the instruction char.
+% \begin{macrocode}
+\def\forest at def@processor#1{%
+ {%
+ \def\forest at dp@double##1{%
+ \gdef\forest at global@temp{\forest at def@processor@{#1}{##1}}%
+ }%
+ \let\\\forest at dp@double
+ \catcode`#1=13
+ \scantokens{\\#1}%
+ }%
+ \forest at global@temp
}
-\csdef{forest at processargs@ins at O}#1\forest at END#2#3\forest at END{% option
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \etotoks\forest at processargs@current{\forestoption{#2}}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@processor@#1#2{%
+ % #1 = instruction char (normal catcode), #2 = instruction char (active)
+ % #3 = default n (optional numeric arg, which precedes any other args;
+ % if the default is empty, this means no optional n)
+ % #4 = args spec,
+ % #5 = code
+ \eappto\forest at process@catregime{%
+ \unexpanded{\let#2}\expandonce{\csname forest at processor@#1\endcsname}%
+ \unexpanded{\catcode`#1=13 }%
+ }%
+ \def\forest at def@processor at inschar{#1}%
+ \forest at def@processor@@
}
-\csdef{forest at processargs@ins at R}#1\forest at END#2#3\forest at END{% register
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \etotoks\forest at processargs@current{\forestregister{#2}}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+% \end{macrocode}
+% If |#1| is non-empty, the processor accepts the optional numeric argument: |#1| is the default.
+% \begin{macrocode}
+\def\forest at def@processor@@#1{%
+ \ifstrempty{#1}{%
+ \forest at def@processor@@non
+ }{%
+ \def\forest at def@processor@@default at n{#1}%
+ \forest at def@processor@@n
+ }%
}
-\csdef{forest at processargs@ins at P}#1\forest at END#2#3\forest at END{% pgfmath expression
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \pgfmathparse{#2}%
- \expandafter\forest at processargs@current\expandafter{\pgfmathresult}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+% \end{macrocode}
+% We need |\relax| below because the next instruction character might get expanded when assigning the optional numerical argument which is not there.
+%
+% No optional n:
+% \begin{macrocode}
+\def\forest at def@processor@@non#1#2{% #1=args spec, #2=code
+ \csedef{forest at processor@\forest at def@processor at inschar}#1{%
+ \relax %% we need this (see above)
+ \unexpanded{#2}%
+ \expandafter\forest at def@processor at debuginfo\expandafter{%
+ \expandafter"\forest at def@processor at inschar"\ifstrempty{#1}{}{(#1)}}%
+ \ignorespaces
+ }%
}
-\csdef{forest at processargs@ins at +}#1\forest at END#2\forest at END{% join processors
- \forest at processargs@appendfalse
+% \end{macrocode}
+% Optional n: |*| after the given default means that the operation should be repeated n times.
+% \begin{macrocode}
+\def\forest at def@processor@@n{%
+ \@ifnextchar*%
+ {\forest at temptrue\forest at def@processor@@n@}%
+ {\forest at tempfalse\forest at def@processor@@n@@}%
+}
+\def\forest at def@processor@@n@*{\forest at def@processor@@n@@}
+\def\forest at def@processor@@n@@#1#2{% #1=args spec, #2=code
+ \csedef{forest at processor@\forest at def@processor at inschar}{%
+ \relax %% we need this (see above)
+ \noexpand\forestprocess at get@n
+ {\forest at def@processor@@default at n}%
+ \expandonce{\csname forest at processor@\forest at def@processor at inschar @\endcsname}%
+ }%
+ \ifforest at temp
+ \csedef{forest at processor@\forest at def@processor at inschar @}{%
+ \noexpand\forest at repeat@n at times{\forest at process@n}{%
+ \expandonce{\csname forest at processor@\forest at def@processor at inschar @rep\endcsname}%
+ }%
+ }%
+ \fi
+ \edef\forest at temp{%
+ \forest at def@processor at inschar
+ \ifforest at temp\else\noexpand\the\forest at process@n\fi
+ "}%
+ \csedef{forest at processor@\forest at def@processor at inschar @\ifforest at temp rep\fi}#1{%
+ \unexpanded{#2}%
+ \expandafter\forest at def@processor at debuginfo\expandafter{%
+ \forest at temp
+ \ifstrempty{#1}{}{(#1)}}%
+ }%
+}
+\def\forest at def@processor at debuginfo#1{% #1 = instruction call
+ \ifforestdebug
+ \expandonce{\forest at processor@debuginfo at template{#1}}%
+ \fi
+}
+\def\forest at processor@debuginfo at template#1{%
+ \ifforestdebugprocess
+ \edef\forest at temp@left{\forest at process@left at values}%
+ \edef\forest at temp@right{\forest at process@right at values}%
+ \edef\forest at temp@saved{\forest at process@saved at values}%
+ \typeout{[forest .process]\space\space\space\space After #1: left="\expandonce{\forest at temp@left}", right="\expandonce{\forest at temp@right}", saved="\expandonce{\forest at temp@saved}", type=\forestmathresulttype}%
+ \fi
+}
+% \end{macrocode}
+% A helper macro which puts the optional numeric argument into count |\forest at process@n| (default being |#1|) and then executes control sequence |#2|.
+% \begin{macrocode}
+\newcount\forest at process@n
+\def\forestprocess at get@n#1#2{%
+ \def\forestprocess at default@n{#1}%
+ \let\forestprocess at after@get at n@#2%
+ \afterassignment\forestprocess at get@n@\forest at process@n=0%
+}
+\def\forestprocess at get@n@{%
+ \ifnum\forest at process@n=0
+ \forest at process@n\forestprocess at default@n\relax
+ \fi
+ \forestprocess at after@get at n@
+}
+% \end{macrocode}
+%
+% Definitions of processing instructions. Processors should be defined using |\forest at def@processor|. If they take arguments: yes, they follow, but they were scanned in |\forest at process@catregime|. Processors should manipulate arrays |\forest at process@left@| and |\forest at process@right|. They should set |\def\forestmathresulttype| to |_| not defined, |n| number, |d| dimension, |P| pgfmath or |t| text.
+% \begin{macrocode}
+\forest at def@processor{_}{1}*{}{% no processing, no type
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at letappend\forest at temp
+}
+\forest at def@processor{n}{1}*{}{% numexpr
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at esetappend{\number\numexpr\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{d}{1}*{}{% dimexpr
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at esetappend{\the\dimexpr\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at dimen
+}
+\forest at def@processor{P}{1}*{}{% pgfmath expression
+ \forest at process@right at bottompop\forest at temp
+ \pgfmathparse{\forest at temp}%
+ \forest at process@left at letappend\pgfmathresult
+ \let\forestmathresulttype\forestmathtype at unitless
+}
+\forest at def@processor{t}{1}*{}{% text
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at letappend\forest at temp
+ \let\forestmathresulttype\forestmathtype at textasc
+}
+\forest at def@processor{-}{}{}{% toggle ascending/descending
+ \forest at process@left at toppop\forestmathresult
+ \csname forest at processor@-@\forestmathresulttype\endcsname
+ \forest at process@left at letappend\forestmathresult
+}
+\cslet{forest at processor@-@\forestmathtype at generic}\relax
+\csdef{forest at processor@-@\forestmathtype at count}{%
+ \forestmathadd{\forestmathzero}{-\forestmathresult}}
+\csletcs{forest at processor@-@\forestmathtype at dimen}
+ {forest at processor@-@\forestmathtype at count}
+\csletcs{forest at processor@-@\forestmathtype at unitless}
+ {forest at processor@-@\forestmathtype at count}
+\csdef{forest at processor@-@\forestmathtype at textasc}{%
+ \let\forestmathresulttype\forestmathtype at textdesc}
+\csdef{forest at processor@-@\forestmathtype at textdesc}{%
+ \let\forestmathresulttype\forestmathtype at textasc}
+
+\forest at def@processor{c}{}{}{% to lowercase
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\lowercase\expandafter{\expandafter\def\expandafter\forest at temp\expandafter{\forest at temp}}%
+ \forest at process@left at letappend\forest at temp
+}
+\forest at def@processor{C}{}{}{% to uppercase
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\uppercase\expandafter{\expandafter\def\expandafter\forest at temp\expandafter{\forest at temp}}%
+ \forest at process@left at letappend\forest at temp
+}
+% \end{macrocode}
+% Expansions:
+% \begin{macrocode}
+\forest at def@processor{x}{}{}{% expand
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at esetappend{\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at generic
+}
+\forest at def@processor{o}{1}{}{% expand once (actually, \forest at count@n times)
+ \forest at process@right at bottompop\forest at temp
+ \forest at repeat@n at times{\forest at process@n}{%
+ \expandafter\expandafter\expandafter\def
+ \expandafter\expandafter\expandafter\forest at temp
+ \expandafter\expandafter\expandafter{\forest at temp}%
+ }%
+ \expandafter\forest at process@left at setappend\expandafter{\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at generic
+}
+% \end{macrocode}
+% Access to \foRest; data.
+% \begin{macrocode}
+\forest at def@processor{O}{1}*{}{% option
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\forestRNO at getvalueandtype\expandafter{\forest at temp}\forest at tempvalue\forest at temp@type
+ \let\forestmathresulttype\forest at temp@type
+ \forest at process@left at letappend\forest at tempvalue
+}
+\forest at def@processor{R}{1}*{}{% register
+ \forest at process@right at bottompop\forest at temp
+ \forestrget{\forest at temp}\forest at tempvalue
+ \forest at process@left at letappend\forest at tempvalue
+ \pgfkeysgetvalue{/forest/\forest at temp/@type}\forest at temp@type
+ \let\forestmathresulttype\forest at temp@type
+}
+% \end{macrocode}
+% The following processors muck about with the argument / result list.
+% \begin{macrocode}
+\forest at def@processor{+}{1}*{}{% join processors = pop one from result
+ \forest at process@left at toppop\forest at temp
+ \forest at process@right at letprepend\forest at temp
+}
+\forest at def@processor{u}{}{}{% ungroup: remove braces and leave in the argument list
+ \forest at process@right at bottompop\forest at temp
+ \forest at temparray@clear
+ \let\forestmathresulttype\forestmathtype at generic
+ \let\forest at topextend@next\forest at processor@u@
+ \expandafter\forest at temparray@topextend\forest at temp\forest at eov
+}
+\def\forest at processor@u@{%
+ \forest at loop
+ \ifnum\forest at temparray@N>0
+ \forest at temparray@toppop\forest at temp
+ \expandafter\forest at process@right at setprepend\expandafter{\expandafter{\forest at temp}}%
+ \forest at repeat
+}
+\def\forest at process@check at mn#1#2#3#4{%
+ % #1 = processor, #2 = given n, #3/#4 = lower/upper bound (inclusive)
+ \ifnum#3>#2\relax
+ \forest at process@check at n@error{#1}{#2}{#3<=}{<=#4}%
+ \else
+ \ifnum#4<#2\relax
+ \forest at process@check at n@error{#1}{#2}{#3<=}{<=#4}%
+ \fi
+ \fi
+}
+\def\forest at process@check at m#1#2#3{%
+ % #1 = processor, #2 = given n, #3 = lower bound (inclusive)
+ \ifnum#2<#3\relax
+ \forest at process@check at n@error{#1}{#2}{#3<=}{}%
+ \fi
+}
+\def\forest at process@check at n@error#1#2#3#4{%
+ \PackageError{forest}{'.process' instruction '#1' requires a numeric modifier #3n#4, but n="#2" was given.}{}%
+}
+\newif\ifforest at process@W
+\forest at def@processor{w}{1}{}{% consuming wrap: first test 1<=#1<=9
+ \forest at process@Wtrue
+ \forest at process@check at mn{w}{0\the\forest at process@n}{1}{9}%
+ \expandafter\forest at processor@wW@\expandafter{\the\forest at process@n}%
+}
+\forest at def@processor{W}{1}{}{% nonconsuming wrap: first test 1<=#1<=9
+ \forest at process@Wfalse
+ \forest at process@check at mn{W}{0\the\forest at process@n}{1}{9}%
+ \expandafter\forest at processor@wW@\expandafter{\the\forest at process@n}%
+}
+\def\forest at processor@wW@#1{%
+ \forest at process@left at checkindex{\forest at process@left at N-#1}%
\edef\forest at marshal{%
- \unexpanded{\forest at processargs@getins#1\forest at END}{\the\forest at processargs@current}\unexpanded{#2\forest at END}%
+ \edef\noexpand\forest at temp@args{%
+ \noexpand\forest at process@left at valuesfromrange
+ {\number\numexpr\forest at process@left at N-#1}%
+ {\the\forest at process@left at N}%
+ }%
}\forest at marshal
+ \ifforest at process@W
+ \advance\forest at process@left at N-#1\relax
+ \fi
+ \forest at process@right at bottompop\forest at temp@macrobody
+ \expandafter\forest at def@n\expandafter\forest at process@temp at macro\expandafter{\expandafter#1\expandafter}\expandafter{\forest at temp@macrobody}%
+ \expandafter\expandafter\expandafter\forest at process@left at setappend\expandafter\expandafter\expandafter{\expandafter\forest at process@temp at macro\forest at temp@args}%
+ \let\forestmathresulttype\forestmathtype at generic
}
-\csdef{forest at processargs@ins at r}#1\forest at END#2#3\forest at END{% reverse keylist
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \forest at processargs@current{}%
- \pgfqkeys{/forest}{split={#2}{,}{reverse at keylist}}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@n#1#2{\csname forest at def@n@#2\endcsname#1}
+\csdef{forest at def@n at 1}#1{\def#1##1}
+\csdef{forest at def@n at 2}#1{\def#1##1##2}
+\csdef{forest at def@n at 3}#1{\def#1##1##2##3}
+\csdef{forest at def@n at 4}#1{\def#1##1##2##3##4}
+\csdef{forest at def@n at 5}#1{\def#1##1##2##3##4##5}
+\csdef{forest at def@n at 6}#1{\def#1##1##2##3##4##5##6}
+\csdef{forest at def@n at 7}#1{\def#1##1##2##3##4##5##6##7}
+\csdef{forest at def@n at 8}#1{\def#1##1##2##3##4##5##6##7##8}
+\csdef{forest at def@n at 9}#1{\def#1##1##2##3##4##5##6##7##8##9}
+% \end{macrocode}
+% Save last |n| arguments from the left side into a special place. |s| deletes them from the left side, |S| keeps them there as well.
+% \begin{macrocode}
+\forest at def@processor{s}{1}{}{%
+ \forest at temptrue % delete the originals
+ \expandafter\forest at processor@save\expandafter{%
+ \the\numexpr\forest at process@left at N-\forest at process@n}}
+\forest at def@processor{S}{1}{}{%
+ \forest at tempfalse % keep the originals
+ \expandafter\forest at processor@save\expandafter{%
+ \the\numexpr\forest at process@left at N-\forest at process@n}}
+\def\forest at processor@save#1{%
+ \forest at process@left at checkindex{#1}%
+ \forest at temp@count#1
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@left at N\relax
+ \forest at process@left at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@saved at letappend\forest at temp
+ \advance\forest at temp@count+1
+ \forest at repeat
+ \let\forest at process@savedtype\forestmathresulttype
+ \ifforest at temp
+ \forest at process@left at N=#1
+ \fi
}
+% \end{macrocode}
+% Load |n| arguments from the end of the special place to the left side. If $n=0$, load the entire special place. |l| deletes the args from the special place, |L| keeps them there as well.
+% \begin{macrocode}
+\forest at def@processor{l}{0}{}{%
+ \forest at temptrue
+ \forest at processor@U@@
+}
+\forest at def@processor{L}{0}{}{%
+ \forest at tempfalse
+ \forest at processor@U@@
+}
+
+\def\forest at processor@U@@{%
+ \ifnum\forest at process@n=0
+ \forest at process@n\forest at process@saved at N\relax
+ \fi
+ \expandafter\forest at processor@U@@@\expandafter{%
+ \the\numexpr\forest at process@saved at N-\forest at temp@count}%
+}
+\def\forest at processor@U@@@#1{%
+ \forest at temp@count#1
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@saved at N\relax
+ \forest at process@saved at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@left at letappend\forest at temp
+ \advance\forest at temp@count1
+ \forest at repeat
+ \let\forestmathresulttype\forest at process@savedtype
+ \ifforest at temp
+ \let\forest at process@savedtype\forest at result@type at any
+ \forest at process@saved at N#1
+ \fi
+}
+% \end{macrocode}
+% Boolean operations:
+% \begin{macrocode}
+\forest at def@processor{&}{2}{}{% and
+ \def\forest at tempa{1}%
+ \forest at repeat@n at times{\forest at process@n}{%
+ \forest at process@left at bottompop\forest at tempb
+ \edef\forest at tempa{\ifnum10<\forest at tempa\forest at tempb\space 1\else0\fi}%
+ }%
+ \forest at process@left at esetappend{\forest at tempa}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{|}{2}{}{% or
+ \def\forest at tempa{0}%
+ \forest at repeat@n at times{\forest at process@n}{%
+ \forest at process@left at bottompop\forest at tempb
+ \edef\forest at tempa{\ifnum0=\forest at tempa\forest at tempb\space 0\else1\fi}%
+ }%
+ \forest at process@left at esetappend{\forest at tempa}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{!}{}{}{% not
+ \forest at process@left at toppop\forest at temp
+ \forest at process@left at esetappend{\ifnum0=\forest at temp\space 1\else0\fi}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{?}{}{}{%
+ \forest at process@left at toppop\forest at temp
+ \forest at process@right at bottompop\forest at tempa
+ \forest at process@right at bottompop\forest at tempb
+ \ifnum\forest at temp=0
+ \forest at process@right at letprepend\forest at tempb
+ \else
+ \forest at process@right at letprepend\forest at tempa
+ \fi
+ \let\forestmathresulttype\forestmathtype at generic
+}
+% \end{macrocode}
+% Comparisons. They automatically determine the type (number, dimen, other) of the arguments, by checking what the last processing instruction was.
+% \begin{macrocode}
+\forest at def@processor{=}{}{}{%
+ \forest at process@left at toppop\forest at tempa
+ \forest at process@left at toppop\forest at tempb
+ \forest at process@left at esetappend{\ifx\forest at tempa\forest at tempb 1\else0\fi}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{<}{}{}{%
+ \forest at process@left at toppop\forest at tempb
+ \forest at process@left at toppop\forest at tempa
+ \ifx\forestmathresulttype\forestmathtype at generic
+ \forest at cmp@error\forest at tempa\forest at tempb
+ \else
+ \forestmathlt{\forest at tempa}{\forest at tempb}%
+ \forest at process@left at esetappend{\forestmathresult}%
+ \fi
+}
+\forest at def@processor{>}{}{}{%
+ \forest at process@left at toppop\forest at tempb
+ \forest at process@left at toppop\forest at tempa
+ \ifx\forestmathresulttype\forestmathtype at generic
+ \forest at cmp@error\forest at tempa\forest at tempb
+ \else
+ \forestmathgt{\forest at tempa}{\forest at tempb}%
+ \forest at process@left at esetappend{\forestmathresult}%
+ \fi
+}
+% \end{macrocode}
+% Various.
+% \begin{macrocode}
+\forest at def@processor{r}{}{}{% reverse keylist
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\forest at processor@r@\expandafter{\forest at temp}%
+}
+\def\forest at processor@r@#1{%
+ \forest at temp@toks{}%
+ \def\forest at tempcomma{}%
+ \pgfqkeys{/forest}{split={#1}{,}{process at rk}}%
+ \forest at process@left at esetappend{\the\forest at temp@toks}%
+ \let\forestmathresulttype\forestmathtype at generic
+}
\forestset{%
- reverse at keylist/.code={%
- \epretotoks\forest at processargs@current{#1,}%
- },
+ process at rk/.code={%
+ \epretotoks\forest at temp@toks{#1\forest at tempcomma}%
+ \def\forest at tempcomma{,}%
+ }%
}
% \end{macrocode}
%
@@ -2565,14 +4035,13 @@
}
\def\forest at pgfmathhelper@register at dimen#1#2{%
\forestrget{#2}\forest at temp
- \pgfmathparse{+\forest at temp}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}
\def\forest at pgfmathhelper@register at count#1#2{%
- \forestrget{#2}\forest at temp
- \pgfmathtruncatemacro\pgfmathresult{\forest at temp}%
+ \forestrget{#2}\pgfmathresult
}
\def\forest at declareregisterhandler#1#2{%#1=handler for specific type,#2=option name
- \pgfkeyssetvalue{/forest/#2/node at or@reg}{register}%
+ \pgfkeyssetvalue{/forest/#2/node at or@reg}{}% empty = register (node id=node)
\forest at convert@others at to@underscores{#2}\forest at pgfmathoptionname
\edef\forest at marshal{%
\noexpand#1{/forest/#2}{/forest}{#2}{\forest at pgfmathoptionname}%
@@ -2643,6 +4112,7 @@
\pgfkeyssetvalue{#1/option at name}{#3}%
\pgfkeyssetvalue{#1+/option at name}{#3}%
\pgfkeyssetvalue{#2/+#3/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at generic % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at toks{##1}{#3}}%
}
\def\forest at declareautowrappedtoksregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix
@@ -2667,7 +4137,24 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at dimen % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at dimen{##1}{#3}}%
}
\def\forest at declaredimenregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -2674,17 +4161,17 @@
\forest at declarereadonlydimenregister@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{%
#1/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\forestrlet{#3}\forest at temp
},
#1+/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestrve{#3}
\advance\pgfutil at tempdima\forest at temp\relax
\forestreset{#3}{\the\pgfutil at tempdima}%
},
#1-/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestrve{#3}
\advance\pgfutil at tempdima-\forest at temp\relax
\forestreset{#3}{\the\pgfutil at tempdima}%
@@ -2741,7 +4228,24 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at count{##1}{#3}}%
}
\def\forest at declarecountregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -2748,29 +4252,29 @@
\forest at declarereadonlycountregister@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{
#1/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\forestrlet{#3}\forest at temp
},
#1+/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\advance\c at pgf@counta\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
},
#1-/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\advance\c at pgf@counta-\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
},
#1*/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\multiply\c at pgf@counta\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
},
#1:/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\divide\c at pgf@counta\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
@@ -2814,16 +4318,13 @@
\def\forest at declarebooleanregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
\pgfkeysalso{%
#1/.code={%
- \ifstrequal{##1}{1}{%
- \forestrset{#3}{1}%
+ \ifcsdef{forest at bh@\detokenize{##1}}{%
+ \letcs\forest at temp{forest at bh@\detokenize{##1}}%
}{%
- \ifstrequal{##1}{0}{%
- \forestrset{#3}{0}%
- }{%
- \pgfmathifthenelse{##1}{1}{0}%
- \forestrlet{#3}\pgfmathresult
- }%
+ \forestmathtruncatemacro\forest at temp{##1}%
+ \ifx\forest at temp0\else\def\forest at temp{1}\fi
}%
+ \forestrlet{#3}\forest at temp
},
#1/.default=1,
#2/not #3/.code={\forestrset{#3}{0}},
@@ -2837,6 +4338,7 @@
},
}%
\pgfkeyssetvalue{#1/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at count{##1}{#3}}%
}
\forestset{
@@ -3010,13 +4512,18 @@
preamble'={},
declare autowrapped toks={content}{},
% #1 = which option to split, #2 = separator (one char!), #3 = receiving options
- %%% begin listing region: split_option
- split option/.style n args=3{split/.process args={O}{#1}{#2}{#3}}
- %%% end listing region: split_option
- ,
- split register/.style n args=3{% #1 = which register to split, #2 = separator (one char!), #3 = receiving options
- split/.process args={R}{#1}{#2}{#3},
+ split option/.code n args=3{%
+ \forestRNOget{#1}\forest at temp
+ \edef\forest at marshal{%
+ \noexpand\pgfkeysalso{split={\expandonce{\forest at temp}}\unexpanded{{#2}{#3}}}%
+ }\forest at marshal
},
+ split register/.code n args=3{% #1 = which register to split, #2 = separator (one char!), #3 = receiving options
+ \forestrget{#1}\forest at temp
+ \edef\forest at marshal{%
+ \noexpand\pgfkeysalso{split={\expandonce{\forest at temp}}\unexpanded{{#2}{#3}}}%
+ }\forest at marshal
+ },
TeX={%
\def\forest at split@sourcevalues{}%
\def\forest at split@sourcevalue{}%
@@ -3213,7 +4720,7 @@
get node boundary/.code={%
\forestoget{@boundary}\forest at node@boundary
\def#1{}%
- \forest at extendpath#1\forest at node@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}%
+ \forest at extendpath#1\forest at node@boundary{\pgfqpoint{\forestove{x}}{\forestove{y}}}%
},
% get min l tree boundary/.code={%
% \forest at get@tree at boundary{negative}{\the\numexpr\forestove{grow}-90\relax}#1},
@@ -3269,7 +4776,7 @@
\def\forest at get@tree at boundary#1#2#3{%#1=pos/neg,#2=grow,#3=receiving cs
\def#3{}%
\forest at node@getedge{#1}{#2}\forest at temp@boundary
- \forest at extendpath#3\forest at temp@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}%
+ \forest at extendpath#3\forest at temp@boundary{\pgfqpoint{\forestove{x}}{\forestove{y}}}%
}
\def\forest at setter@node{\forest at cn}%
\def\forest at relatednode@option at compat@ignoreinvalidsteps#1{#1}
@@ -3299,33 +4806,31 @@
\forestset{
for tree'/.style 2 args={#1,for children={for tree'={#1}{#2}},#2},
if/.code n args={3}{%
- \pgfmathparse{#1}%
- \ifnum\pgfmathresult=0
+ \forestmathtruncatemacro\forest at temp{#1}%
+ \ifnum\forest at temp=0
\@escapeif{\pgfkeysalso{#3}}%
\else
\@escapeif{\pgfkeysalso{#2}}%
\fi
},
+ %LaTeX if/.code n args={3}{#1{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}},
if nodewalk valid/.code n args={3}{%
- \edef\forest at marshal{%
- \unexpanded{\forest at forthis{%
- \forest at nodewalk{%
- on invalid={fake}{#1},
- TeX={\global\let\forest at global@temp\forest at cn}
- }{}%
- }%
- \def\forest at cn}{\forest at cn}\unexpanded{%
- \ifnum\forest at global@temp=0
- \@escapeif{\pgfkeysalso{#3}}%
- \else
- \@escapeif{\pgfkeysalso{#2}}%
- \fi}%
- }\forest at marshal
+ \forest at forthis{%
+ \forest at configured@nodewalk{independent}{inherited}{fake}{%
+ #1,
+ TeX={\global\let\forest at global@temp\forest at cn}
+ }{}%
+ }%
+ \ifnum\forest at global@temp=0
+ \@escapeif{\pgfkeysalso{#3}}%
+ \else
+ \@escapeif{\pgfkeysalso{#2}}%
+ \fi
},
if nodewalk empty/.code n args={3}{%
\forest at forthis{%
- \forest at nodewalk{%
- on invalid={fake}{#1},
+ \forest at configured@nodewalk{independent}{independent}{fake}{%
+ #1,
TeX={\global\let\forest at global@temp\forest at nodewalk@n},
}{}%
}%
@@ -3335,11 +4840,18 @@
\@escapeif{\pgfkeysalso{#3}}%
\fi
},
+ if current nodewalk empty/.code 2 args={%
+ \ifnum\forest at nodewalk@n=0
+ \@escapeif{\pgfkeysalso{#1}}%
+ \else
+ \@escapeif{\pgfkeysalso{#2}}%
+ \fi
+ },
where/.style n args={3}{for tree={if={#1}{#2}{#3}}},
where nodewalk valid/.style n args={3}{for tree={if nodewalk valid={#1}{#2}{#3}}},
where nodewalk empty/.style n args={3}{for tree={if nodewalk empty={#1}{#2}{#3}}},
repeat/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\expandafter\forest at repeatkey\expandafter{\forest at temp}{#2}%
},
until/.code 2 args={%
@@ -3346,7 +4858,7 @@
\ifstrempty{#1}{%
\forest at untilkey{\ifnum\forest at cn=0\else\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at untilkey{\pgfmathifthenelse{#1}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at untilkey{\forestmath at if{#1}{\forestloopbreak}{}}{#2}%
}%
},
while/.code 2 args={%
@@ -3353,7 +4865,7 @@
\ifstrempty{#1}{%
\forest at untilkey{\ifnum\forest at cn=0\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at untilkey{\pgfmathifthenelse{not(#1)}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at untilkey{\forestmath at if{#1}{}{\forestloopbreak}}{#2}%
}%
},
do until/.code 2 args={%
@@ -3360,7 +4872,7 @@
\ifstrempty{#1}{%
\forest at dountilkey{\ifnum\forest at cn=0\else\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at dountilkey{\pgfmathifthenelse{#1}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at dountilkey{\forestmath at if{#1}{\forestloopbreak}{}}{#2}%
}%
},
do while/.code 2 args={%
@@ -3367,7 +4879,7 @@
\ifstrempty{#1}{%
\forest at dountilkey{\ifnum\forest at cn=0\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at dountilkey{\pgfmathifthenelse{not(#1)}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at dountilkey{\forestmath at if{#1}{}{\forestloopbreak}}{#2}%
}%
},
until nodewalk valid/.code 2 args={%
@@ -3478,50 +4990,176 @@
\forest at aggregate@pgfmathpostparse at macro
}
\let\forest at aggregate@pgfmathpostparse\relax
-\pgfkeys{
+\forestset{
/handlers/.aggregate/.code n args=4{%
- % #1 = start value
- % #2 = pgfmath expression for every step
- % #3 = pgfmath expression for after walk
+ % #1 = start value (forestmath)
+ % #2 = forestmath expression that calculates "aggregate result" at each step
+ % #3 = forestmath expression that calculates "aggregate result" at the end of the nodewalk
% #4 = nodewalk
- \edef\forest at marshal{%
- \unexpanded{\forest at aggregate{#1}{#2}{#3}{#4}}{\pgfkeyscurrentpath}%
- }\forest at marshal
+ \forest at aggregate@handler{\forest at aggregate@generic{#1}{#2}{#3}{#4}}%
},
- /handlers/.sum/.style 2 args={/handlers/.aggregate={0}{(##1)+(#1)}{##1}{#2}},
- /handlers/.count/.style={/handlers/.aggregate={0}{1+(##1)}{##1}{#1}},
- /handlers/.average/.style 2 args={/handlers/.aggregate={0}{(##1)+(#1)}{##1/\forestregister{aggregate n}}{#2}},
- /handlers/.product/.style 2 args={/handlers/.aggregate={1}{(#1)*(##1)}{##1}{#2}},
- /handlers/.min/.style 2 args={/handlers/.aggregate={}{min(#1,##1)}{##1}{#2}},
- /handlers/.max/.style 2 args={/handlers/.aggregate={}{max(#1,##1)}{##1}{#2}},
- /forest/declare count register={aggregate n},
+ /handlers/.sum/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@sum{#1}{#2}}%
+ },
+ /handlers/.count/.code={% #1=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@count{#1}}%
+ },
+ /handlers/.average/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@average{#1}{#2}}%
+ },
+ /handlers/.product/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@product{#1}{#2}}%
+ },
+ /handlers/.min/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@min{#1}{#2}}%
+ },
+ /handlers/.max/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@max{#1}{#2}}%
+ },
+ declare count register={aggregate n},
+ declare toks register={aggregate value},
+ declare toks register={aggregate result},
+ aggregate result={},
}
-
-\def\forest at aggregate#1#2#3#4#5{%
- % #5 = current path
- \def\forest at aggregate@result{#1}%
- \forest at forthis{%
- \forestrset{aggregate n}{0}%
- \forest at nodewalk{#4}{%
- TeX={%
- \forestreset{aggregate n}{\number\numexpr\forestrv{aggregate n}+1}%
- \def\forest at marshal##1{\pgfmathparse{#2}}%
- \expandafter\forest at marshal\expandafter{\forest at aggregate@result}%
- \let\forest at aggregate@result\pgfmathresult
- }%
- }{}%
+\def\forest at aggregate@handler#1{%
+ \edef\forest at marshal{%
+ \unexpanded{%
+ #1%
+ }{%
+ \noexpand\pgfkeysalso{\pgfkeyscurrentpath/.register=aggregate result}%
}%
- \def\forest at marshal##1{\pgfmathparse{#3}}%
- \expandafter\forest at marshal\expandafter{\forest at aggregate@result}%
- \let\forest at aggregate@result\pgfmathresult
- \let\forest at temp@pgfmathpostparse\pgfmathpostparse
- \let\pgfmathpostparse\forest at aggregate@pgfmathpostparse
- \pgfmathqparse{\forest at aggregate@result pt}%
- \let\pgfmathpostparse\forest at temp@pgfmathpostparse
- \let\forest at aggregate@result\pgfmathresult
- \pgfkeysalso{#5/.expand once=\forest at aggregate@result}%
+ }\forest at marshal
}
+\def\forest at aggregate@pgfmathfunction at finish{%
+ \forestrget{aggregate result}\pgfmathresult
+}
+\pgfmathdeclarefunction{aggregate}{4}{%
+ \forest at aggregate@generic{#1}{#2}{#3}{#4}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_count}{1}{%
+ \forest at aggregate@sum{#1}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_sum}{2}{%
+ \forest at aggregate@sum{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_product}{2}{%
+ \forest at aggregate@product{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_average}{2}{%
+ \forest at aggregate@average{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_min}{2}{%
+ \forest at aggregate@min{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_max}{2}{%
+ \forest at aggregate@max{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
% \end{macrocode}
+% Define particular aggregate functions.
+% \begin{macrocode}
+\def\forest at aggregate#1#2#3#4#5#6{% #1...#5=real args,
+ % #6=what to do with |aggregate result| register
+ % #1 = start value (forestmath)
+ % #2 = forestmath expression that calculates "aggregate current" at each step
+ % #3 = forestmath expression that calculates "aggregate result" at each step
+ % #4 = forestmath expression that calculates "aggregate result" at the end of the nodewalk
+ % #5 = nodewalk
+ \forest at saveandrestoreregister{aggregate result}{%
+ \forest at saveandrestoreregister{aggregate n}{%
+ \forest at aggregate@{#1}{#2}{#3}{#4}{#5}%
+ #6%
+ }%
+ }%
+}
+\def\forest at aggregate@generic#1#2#3#4{\forest at aggregate
+ {\forestmathparse{#1}}%
+ {}%
+ {\forestmathparse{#2}}%
+ {\forestmathparse{#3}}%
+ {#4}%
+}
+\def\forest at aggregate@sum#1#2{\forest at aggregate
+ {\forestmath at convert@fromto\forestmathtype at count\forestmathtype at generic{0}}%
+ {\forestmathparse{#1}}%
+ {\forestmathadd{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@count#1{\forest at aggregate
+ {\def\forestmathresult{1}}%
+ {\def\forestmathresult{1}}%
+ {\edef\forestmathresult{\the\numexpr\forestregister{aggregate result}+1}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#1}%
+}
+\def\forest at aggregate@average#1#2{\forest at aggregate
+ {\forestmath at convert@fromto\forestmathtype at count\forestmathtype at generic{0}}%
+ {\forestmathparse{#1}}%
+ {\forestmathadd{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestmathdivide at P{\forestregister{aggregate result}}{\forestregister{aggregate n}}}%
+ {#2}%
+}
+\def\forest at aggregate@product#1#2{\forest at aggregate
+ {\forestmath at convert@fromto\forestmathtype at count\forestmathtype at generic{1}}%
+ {\forestmathparse{#1}}%
+ {\forestmathmultiply{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@min#1#2{\forest at aggregate
+ {\def\forestmathresult{}}%
+ {\forestmathparse{#1}}%
+ {\forestmathmin{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@max#1#2{\forest at aggregate
+ {\def\forestmathresult{}}%
+ {\forestmathparse{#1}}%
+ {\forestmathmax{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+% \end{macrocode}
+% Actual computation.
+% \begin{macrocode}
+\def\forest at aggregate@#1#2#3#4#5{%
+ % #1 = start value (forestmath)
+ % #2 = forestmath expression that calculates "aggregate current" at each step
+ % #3 = forestmath expression that calculates "aggregate result" at each step
+ % #4 = forestmath expression that calculates "aggregate result" at the end of the nodewalk
+ % #5 = nodewalk
+ #1%
+ \forestrlet{aggregate result}\forestmathresult
+ \forestrset{aggregate value}{}%
+ \forestrset{aggregate n}{0}%
+ \forest at forthis{%
+ \forest at nodewalk{#5}{%
+ TeX={%
+ \forestreset{aggregate n}{\number\numexpr\forestrv{aggregate n}+1}%
+ #2%
+ \forestrlet{aggregate value}\forestmathresult
+ #3%
+ \forestrlet{aggregate result}\forestmathresult
+ }%
+ }{}%
+ }%
+ #4%
+ \let\forest at temp@pgfmathpostparse\pgfmathpostparse
+ \let\pgfmathpostparse\forest at aggregate@pgfmathpostparse
+ \forestmath at convert@to\forestmathtype at dimen{\forestmathresult}
+ \pgfmathqparse{\forestmathresult}%
+ \let\pgfmathpostparse\forest at temp@pgfmathpostparse
+ \forestrlet{aggregate result}\pgfmathresult
+}
+% \end{macrocode}
% \subsubsection{\texttt{pgfmath} extensions}
%
% \begin{macrocode}
@@ -3539,7 +5177,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{min at s}}%
+ \edef\forest at temp{\forestove{min at s}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\pgfmathdeclarefunction{min_l}{2}{% #1 = node, #2 = context node (for growth rotation)
@@ -3546,7 +5185,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{min at l}}%
+ \edef\forest at temp{\forestove{min at l}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\pgfmathdeclarefunction{max_s}{2}{% #1 = node, #2 = context node (for growth rotation)
@@ -3553,7 +5193,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{max at s}}%
+ \edef\forest at temp{\forestove{max at s}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\pgfmathdeclarefunction{max_l}{2}{% #1 = node, #2 = context node (for growth rotation)
@@ -3560,7 +5201,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{max at l}}%
+ \edef\forest at temp{\forestove{max at l}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\def\forest at compute@minmax at ls#1{% #1 = nodewalk; in the context of which node?
@@ -3568,7 +5210,7 @@
\pgftransformreset
\forest at forthis{%
\forest at nameandgo{#1}%
- \pgftransformrotate{-\forestove{grow}}%
+ \forest at pgfqtransformrotate{-\forestove{grow}}%
}%
\forestoget{min x}\forest at temp@minx
\forestoget{min y}\forest at temp@miny
@@ -3617,10 +5259,10 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\ifnum\forest at cn=0
- \def\pgfmathresult{0pt}%
+ \def\pgfmathresult{0}%
\else
\forestoget{#2}\forest at temp
- \pgfmathparse{+\forest at temp}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
\fi
}%
}
@@ -3630,8 +5272,7 @@
\ifnum\forest at cn=0
\def\pgfmathresult{0}%
\else
- \forestoget{#2}\forest at temp
- \pgfmathtruncatemacro\pgfmathresult{\forest at temp}%
+ \forestoget{#2}\pgfmathresult
\fi
}%
}
@@ -3679,21 +5320,30 @@
\def\forest at nodewalk@config at history@inherited at before{}
\let\forest at nodewalk@config at history@inherited at after\forest at nodewalk@config at history@independent at after
\def\forest at nodewalk#1#2{% #1 = nodewalk, #2 = every step keylist
- \def\forest at nodewalk@config at everystep@method{independent}%
- \def\forest at nodewalk@config at history@method{independent}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at Nodewalk{#1}{#2}%
- }%
+ \forest at configured@nodewalk{independent}{independent}{inherited}{#1}{#2}%
}
+\def\forest at configured@nodewalk#1#2#3#4#5{%
+ % #1 = every step method, #2 = history method, #3 = on invalid
+ % #4 = nodewalk, #5 = every step keylist
+ \def\forest at nodewalk@config at everystep@method{#1}%
+ \def\forest at nodewalk@config at history@method{#2}%
+ \def\forest at nodewalk@config at oninvalid{#3}%
+ \forest at Nodewalk{#4}{#5}%
+}
+\def\forest at nodewalk@oninvalid at inherited@text{inherited}
\def\forest at Nodewalk#1#2{% #1 = nodewalk, #2 = every step keylist
+ \ifx\forest at nodewalk@config at oninvalid\forest at nodewalk@oninvalid at inherited@text
+ \edef\forest at nodewalk@config at oninvalid{\forest at nodewalk@oninvalid}%
+ \fi
\edef\forest at marshal{%
\noexpand\pgfqkeys{/forest/nodewalk}{\unexpanded{#1}}%
\csname forest at nodewalk@config at everystep@\forest at nodewalk@config at everystep@method @after\endcsname
\csname forest at nodewalk@config at history@\forest at nodewalk@config at history@method @after\endcsname
+ \edef\noexpand\forest at nodewalk@oninvalid{\forest at nodewalk@oninvalid}%
}%
\csname forest at nodewalk@config at everystep@\forest at nodewalk@config at everystep@method @before\endcsname{#2}%
\csname forest at nodewalk@config at history@\forest at nodewalk@config at history@method @before\endcsname
+ \edef\forest at nodewalk@oninvalid{\forest at nodewalk@config at oninvalid}%
\forest at nodewalk@fakefalse
\forest at marshal
}
@@ -3713,25 +5363,27 @@
\def\forest at nodewalk@oninvalid{error}
\def\forest at nodewalk@makestep{%
\ifnum\forest at cn=0
- \csname forest at nodewalk@makestep at oninvalid@\forest at nodewalk@config at oninvalid\endcsname
+ \csname forest at nodewalk@makestep at oninvalid@\forest at nodewalk@oninvalid\endcsname
\else
\forest at nodewalk@makestep@
\fi
}
-\def\forest at nodewalk@makestep at oninvalid@step{\forest at nodewalk@makestep@}
+\csdef{forest at nodewalk@makestep at oninvalid@error if real}{\ifforest at nodewalk@fake\expandafter\forest at nodewalk@makestep@\else\expandafter\forest at nodewalk@makestep at oninvalid@error\fi}
+\csdef{forest at nodewalk@makestep at oninvalid@last valid}{%
+ \forest at nodewalk@tolastvalid
+ \ifforestdebugnodewalks\forest at nodewalk@makestep at invalidtolastvalid@debug\fi}%
\def\forest at nodewalk@makestep at oninvalid@error{\PackageError{forest}{nodewalk stepped to the invalid node\MessageBreak nodewalk stack: "\forest at nodewalk@currentstepname"}{}}%
\let\forest at nodewalk@makestep at oninvalid@fake\relax
\def\forest at nodewalk@makestep at oninvalid@compatfake{%
- \forest at deprecated{last step in stack "\forest at nodewalk@currentstepname", which stepped on an invalid node; enabled by "compat=ignoreinvalidsteps". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}%
+ \forest at deprecated{last step in stack "\forest at nodewalk@currentstepname", which stepped on an invalid node; enabled by "compat=1.0-forstep". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}%
}%
-\def\forest at nodewalk@makestep at oninvalid@inherited{\csname forest at nodewalk@makestep at oninvalid@\forest at nodewalk@oninvalid\endcsname}
\def\forest at nodewalk@makestep@{%
+ \ifforestdebugnodewalks\forest at nodewalk@makestep at debug\fi
\ifforest at nodewalk@fake
\else
\edef\forest at nodewalk@n{\number\numexpr\forest at nodewalk@n+1}%
\epreto\forest at nodewalk@historyback{\forest at cn,}%
\def\forest at nodewalk@historyforward{0,}%
- \ifforestdebugnodewalks\forest at nodewalk@makestep at debug\fi
\forest at process@keylist at register{every step}%
\fi
}
@@ -3740,6 +5392,11 @@
\noexpand\typeout{\ifforest at nodewalk@fake fake \fi "\forest at nodewalk@currentstepname" step to node id=\forest at cn, content=\forestoption{content}}%
}\forest at marshal
}%
+\def\forest at nodewalk@makestep at invalidtolastvalid@debug{%
+ \edef\forest at marshal{%
+ \noexpand\typeout{\ifforest at nodewalk@fake fake \fi "\forest at nodewalk@currentstepname" step to invalid node, (fake) return to last valid id=\forest at cn, content=\forestoption{content}}%
+ }\forest at marshal
+}%
\def\forest at handlers@savecurrentpath{%
\edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}%
\let\forest at currentkey\pgfkeyscurrentkey
@@ -3844,6 +5501,8 @@
{\noexpand\forest at forstepwrapper{#1\ifnum\forest at nodewalkstephandler@nargs>0=\fi\forest at util@nargs{####}{\number\numexpr\forest at nodewalkstephandler@nargs}{0}}{####\number\numexpr\forest at nodewalkstephandler@nargs+1}},
}%
\fi\fi
+ % Uncomment this to collect a list of for-based spatial propagators
+ %\appto\bigbadforlist{[#1]}%
\fi
},
}
@@ -3856,7 +5515,7 @@
% |\forest at forstepwrapper| is defined so that it can be changed by |compat| to create unfailable spatial propagators from v1.0.
% \begin{macrocode}
\def\forest at forstepwrapper#1#2{\forest at forthis{\forest at nodewalk{#1}{#2}}}
-\def\forest at util@nargs#1#2#3{% #1 = prefix (#, ##, ...), #2 = n args, #3=start; returns {#start}{#start+1}...{#start+n}
+\def\forest at util@nargs#1#2#3{% #1 = prefix (#, ##, ...), #2 = n args, #3=start; returns {#start+1}...{#start+n}
\ifnum#2>0 {#1\number\numexpr#3+1}\fi
\ifnum#2>1 {#1\number\numexpr#3+2}\fi
\ifnum#2>2 {#1\number\numexpr#3+3}\fi
@@ -3868,7 +5527,11 @@
\ifnum#2>8 {#1\number\numexpr#3+9}\fi
}
\def\forest at nodewalk@start at oninvalid@fake#1{}
-\def\forest at nodewalk@start at oninvalid@real#1{}
+\def\forest at nodewalk@start at oninvalid@compatfake#1{%
+ \forest at deprecated{last step in stack "\forest at nodewalk@currentstepname", which started from an invalid node; enabled by "compat=1.0-forstep". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}%
+}%
+\let\forest at nodewalk@start at oninvalid@errorifreal\forest at nodewalk@start at oninvalid@fake % the step will be to an invalid node anyway
+\let\forest at nodewalk@start at oninvalid@lastvalid\forest at nodewalk@start at oninvalid@fake
\def\forest at nodewalk@start at oninvalid@error#1{\PackageError{forest}{nodewalk step "#1" cannot start at the invalid node}{}}
% \end{macrocode}
% Define long-form single-step walks.
@@ -3917,7 +5580,7 @@
},
define long step={next leaf}{style,strip fake steps=false}{group={do until={n_children()==0}{next node}}},
define long step={previous leaf}{style,strip fake steps=false}{group={do until={n_children()==0}{previous node}}},
- define long step={next on tier}{autostep}{%
+ define long step={next on tier}{autostep,n args=1}{%
\def\forest at temp{#1}%
\ifx\forest at temp\pgfkeysnovalue at text
\forestoget{tier}\forest at nodewalk@giventier
@@ -3924,14 +5587,14 @@
\else
\def\forest at nodewalk@giventier{#1}%
\fi
- \edef\forest at cn{\forest at node@linearnextnotdescendantid}%
+ \edef\forest at cn{\forest at node@linearnextid}%
\safeloop
- \forestoget{tier}\forest at nodewalk@tier
- \unless\ifx\forest at nodewalk@tier\forest at nodewalk@giventier
+ \forest at nodewalk@gettier
+ \ifforest at temp
\edef\forest at cn{\forest at node@linearnextid}%
\saferepeat
},
- define long step={previous on tier}{autostep}{%
+ define long step={previous on tier}{autostep,n args=1}{%
\def\forest at temp{#1}%
\ifx\forest at temp\pgfkeysnovalue at text
\forestoget{tier}\forest at nodewalk@giventier
@@ -3940,10 +5603,24 @@
\fi
\safeloop
\edef\forest at cn{\forest at node@linearpreviousid}%
- \forestoget{tier}\forest at nodewalk@tier
- \unless\ifx\forest at nodewalk@tier\forest at nodewalk@giventier
- \saferepeat
+ \forest at nodewalk@gettier
+ \ifforest at temp
+ \saferepeat
},
+ TeX={%
+ \def\forest at nodewalk@gettier{%
+ \ifnum\forest at cn=0
+ \forest at tempfalse
+ \else
+ \forestoget{tier}\forest at temp
+ \ifx\forest at temp\forest at nodewalk@giventier
+ \forest at tempfalse
+ \else
+ \forest at temptrue
+ \fi
+ \fi
+ }%
+ },
%
define long step={root}{autostep,must start at valid node=false}{%
\edef\forest at cn{\forest at node@rootid}},
@@ -3953,7 +5630,7 @@
define long step={origin}{autostep,must start at valid node=false}{\edef\forest at cn{\forest at nodewalk@origin}},
%
define long step={n}{autostep,n args=1}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\edef\forest at cn{\forest at node@nthchildid{\forest at temp@n}}%
},
define long step={n}{autostep,make for=false,n args=1}{%
@@ -3963,19 +5640,19 @@
\ifx\forest at nodewalk@temp\pgfkeysnovalue at text
\edef\forest at cn{\forestove{@next}}%
\else
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\edef\forest at cn{\forest at node@nthchildid{\forest at temp@n}}%
\fi
},
define long step={n'}{autostep,n args=1}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\edef\forest at cn{\forest at node@nbarthchildid{\forest at temp@n}}%
},
define long step={to tier}{autostep,n args=1}{%
\def\forest at nodewalk@giventier{#1}%
\safeloop
- \forestoget{tier}\forest at nodewalk@tier
- \unless\ifx\forest at nodewalk@tier\forest at nodewalk@giventier
+ \forest at nodewalk@gettier
+ \ifforest at temp
\forestoget{@parent}\forest at cn
\saferepeat
},
@@ -3992,45 +5669,35 @@
\def\forest at nodewalk@config at everystep@method{independent}%
\def\forest at nodewalk@config at history@method{shared}%
\def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \pgfqkeys{/forest/nodewalk at config}{#1}%
- \forest at Nodewalk{#2}{#3}%
- }%
+ \pgfqkeys{/forest/nodewalk at config}{#1}%
+ \forest at Nodewalk{#2}{#3}%
},
define long step={nodewalk}{n args=2, at bare}{% #1 = nodewalk, #2 = every step
\forest at nodewalk{#1}{#2}%
},
- define long step={nodewalk'}{n args=1, at bare}{% #1 = nodewalk, #2 = every step
- \def\forest at nodewalk@config at everystep@method{inherited}%
- \def\forest at nodewalk@config at history@method{independent}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at Nodewalk{#1}{}%
- }%
+ define long step={nodewalk'}{n args=1, at bare}{% #1 = nodewalk
+ \forest at configured@nodewalk{inherited}{independent}{inherited}{#1}{}%
},
- % these must be defined explicitely, as prefix "for" normally introduces the every-step keylist
- for nodewalk/.code 2 args={%
+ % these "for ..." keys must be defined explicitely
+ % (and copied into node keyspace manually),
+ % as prefix "for" normally introduces the every-step keylist
+ define long step={for nodewalk}{n args=2, at bare}{% #1 = nodewalk, #2 = every step
\forest at forthis{\forest at nodewalk{#1}{#2}}},
- for nodewalk'/.code={%
- \def\forest at nodewalk@config at everystep@method{inherited}%
- \def\forest at nodewalk@config at history@method{independent}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at forthis{\forest at Nodewalk{#1}{}}%
+ define long step={for nodewalk'}{n args=1, at bare}{% #1 = nodewalk
+ \forest at forthis{%
+ \forest at configured@nodewalk{inherited}{independent}{inherited}{#1}{}%
}%
},
- for Nodewalk/.code n args=3{% #1 = config, #2 = nodewalk, #3 = every-step
- \def\forest at nodewalk@config at everystep@method{inherited}%
- \def\forest at nodewalk@config at history@method{independent}%
+ define long step={for Nodewalk}{n args=3, at bare}{% #1 = config, #2 = nodewalk, #3 = every-step
+ \def\forest at nodewalk@config at everystep@method{independent}%
+ \def\forest at nodewalk@config at history@method{shared}%
\def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \pgfqkeys{/forest/nodewalk at config}{#1}%
- \forest at forthis{\forest at Nodewalk{#2}{#3}}%
- }%
+ \pgfqkeys{/forest/nodewalk at config}{#1}%
+ \forest at forthis{\forest at Nodewalk{#2}{#3}}%
},
- copy command key={/forest/for nodewalk}{/forest/nodewalk/for nodewalk},
- copy command key={/forest/for nodewalk'}{/forest/nodewalk/for nodewalk'},
- copy command key={/forest/for Nodewalk}{/forest/nodewalk/for Nodewalk},
+ copy command key={/forest/nodewalk/Nodewalk}{/forest/Nodewalk},
+ copy command key={/forest/nodewalk/for nodewalk}{/forest/for nodewalk},
+ copy command key={/forest/nodewalk/for Nodewalk}{/forest/for Nodewalk},
declare keylist register=every step,
every step'={},
%%% begin nodewalk config
@@ -4050,23 +5717,25 @@
on at invalid/.is choice,
on at invalid/error/.code={},
on at invalid/fake/.code={},
- on at invalid/step/.code={},
+ on at invalid/error if real/.code={},
+ on at invalid/last valid/.code={},
on at invalid/inherited/.code={},
on invalid/.store in=\forest at nodewalk@config at oninvalid,
on invalid/.prefix style={on at invalid=#1},
%%% end nodewalk config
}
+\newtoks\forest at nodewalk@branch at toks
\forestset{
declare toks register=branch at temp@toks,
branch at temp@toks={},
declare keylist register=branched at nodewalk,
branched at nodewalk={},
- define long step={branch}{n args=1, at bare,style}{@branch={#1}{branch at build@realstep,branch at build@fakestep}},
- define long step={branch'}{n args=1, at bare,style}{@branch={#1}{branch at build@realstep}},
+ define long step={branch}{n args=1, at bare,make for,style}{@branch={#1}{branch at build@realstep,branch at build@fakestep}},
+ define long step={branch'}{n args=1, at bare,make for,style}{@branch={#1}{branch at build@realstep}},
@branch/.style 2 args={%
save and restore register={branched at nodewalk}{
branch at temp@toks={},
- split/.process args={r}{#1}{,}{#2},
+ split/.process={r}{#1}{,}{#2},
branch at temp@style/.style/.register=branch at temp@toks,
branch at temp@style,
branch at temp@style/.style/.register=branched at nodewalk,
@@ -4082,7 +5751,7 @@
branch at temp@toks/.expanded={for nodewalk={\unexpanded{#1}}{
\forestregister{branch at temp@toks}}},
},
- define long step={group}{autostep}{\forest at go{#1}},
+ define long step={group}{autostep,n args=1}{\forest at go{#1}},
nodewalk/fake/.code={%
\forest at saveandrestoreifcs{forest at nodewalk@fake}{%
\forest at nodewalk@faketrue
@@ -4097,7 +5766,7 @@
},
declare keylist register=filtered at nodewalk,
filtered at nodewalk={},
- define long step={filter}{n args=2, at bare,style}{% #1 = nodewalk, #2 = condition
+ define long step={filter}{n args=2, at bare,make for,style}{% #1 = nodewalk, #2 = condition
save and restore register={filtered at nodewalk}{
filtered at nodewalk'={},
Nodewalk=%
@@ -4106,12 +5775,13 @@
{if={#2}{filtered at nodewalk+/.expanded={id=\forestoption{id}}}{}},
filtered at nodewalk@style/.style/.register=filtered at nodewalk,
filtered at nodewalk@style
- }
+ },
},
on at invalid/.is choice,
on at invalid/error/.code={},
on at invalid/fake/.code={},
- on at invalid/step/.code={},
+ on at invalid/error if real/.code={},
+ on at invalid/last valid/.code={},
on invalid/.code 2 args={%
\pgfkeysalso{/forest/on at invalid={#1}}%
\forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
@@ -4121,38 +5791,54 @@
},
define long step={strip fake steps}{n args=1, at bare}{%
\forest at nodewalk@stripfakesteps{\pgfkeysalso{#1}}},
+ define long step={unique}{n args=1}{%
+ \begingroup
+ \def\forest at nodewalk@unique at temp{}%
+ \forest at nodewalk{#1}{%
+ TeX={%
+ \forestoget{unique at visited}\forest at temp
+ \ifx\forest at temp\relax
+ \forestoset{unique at visited}{1}%
+ \eappto\forest at nodewalk@unique at temp{,id=\forest at cn}%
+ \fi
+ }%
+ }%
+ \global\let\forest at global@temp\forest at nodewalk@unique at temp
+ \endgroup
+ \pgfkeysalsofrom{\forest at global@temp}%
+ },
define long step={walk back}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyforward}{\forest at nodewalk@historyback}{\ifnum\forest at cn=0 0\else1\fi}{\forest at temp@n+\ifnum\forest at cn=0 0\else1\fi}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@back at updatehistory
},
nodewalk/walk back/.default=1,
define long step={jump back}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{(#1)+\ifnum\forest at cn=0 0\else1\fi}%
+ \forestmathtruncatemacro\forest at temp@n{(#1)+\ifnum\forest at cn=0 0\else1\fi}%
\forest at nodewalk@walklist{\forest at nodewalk@historyforward}{\forest at nodewalk@historyback}{\forest at temp@n-1}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@back at updatehistory
},
nodewalk/jump back/.default=1,
define long step={back}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyforward}{\forest at nodewalk@historyback}{\ifnum\forest at cn=0 0\else1\fi}{\forest at temp@n+\ifnum\forest at cn=0 0\else1\fi}{\let\forest at cn\forest at nodewalk@cn\forest at saveandrestoreifcs{forest at nodewalk@fake}{\forest at nodewalk@faketrue\forest at nodewalk@makestep}}%
\forest at nodewalk@back at updatehistory
},
nodewalk/back/.default=1,
define long step={walk forward}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyback}{\forest at nodewalk@historyforward}{0}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@forward at updatehistory
},
nodewalk/walk forward/.default=1,
define long step={jump forward}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyback}{\forest at nodewalk@historyforward}{\forest at temp@n-1}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@forward at updatehistory
},
nodewalk/jump forward/.default=1,
define long step={forward}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyback}{\forest at nodewalk@historyforward}{0}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at saveandrestoreifcs{forest at nodewalk@fake}{\forest at nodewalk@faketrue\forest at nodewalk@makestep}}%
\forest at nodewalk@forward at updatehistory
},
@@ -4205,7 +5891,9 @@
\noexpand\forest at nodewalk@sortlist{\noexpand\forest at nodewalk@historyback}{\noexpand\forest at nodewalk@n-\forest at nodewalk@n}\noexpand\forest at sort@descending
}\forest at marshal
},
- sort by/.store in=\forest at nodesort@by,
+ declare keylist register=sort by,
+ copy command key={/forest/sort by'}{/forest/sort by},
+ sort by={},
define long step={save}{n args=2, at bare,make for}{% #1 = name, #2 = nodewalk
\forest at forthis{%
\forest at nodewalk{#2,TeX={%
@@ -4223,6 +5911,21 @@
}\forest at marshal
\csedef{forest at nodewalk@saved@#1}{\forest at nodewalk@walklist at walked}%
},
+ define long step={save append}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{save}{\cseappto}},
+ define long step={save prepend}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{save}{\csepreto}},
+ define long step={walk and save append}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{walk and save}{\cseappto}},
+ define long step={walk and save prepend}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{walk and save}{\csepreto}},
+ nodewalk/save at append@prepend/.code n args=4{%
+ % #1 = nodewalk name, #2 = nodewalk
+ % #3 = "(walk and) save" #4 = \cseappto/\csepreto
+ \pgfkeysalso{#3={@temp}{#2}}%
+ \letcs\forest at temp{forest at nodewalk@saved@@temp}%
+ #4{forest at nodewalk@saved@#1}{\expandonce{\forest at temp}}%
+ },
nodewalk/save history/.code 2 args={% #1 = back, forward
\csedef{forest at nodewalk@saved@#1}{\forest at nodewalk@historyback}%
\csedef{forest at nodewalk@saved@#2}{\forest at nodewalk@historyforward}%
@@ -4313,12 +6016,7 @@
\let\forest at nodewalk@historyback\forest at nodewalk@walklist at walked
}
\def\forest at go#1{%
- \def\forest at nodewalk@config at everystep@method{independent}%
- \def\forest at nodewalk@config at history@method{inherited}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at Nodewalk{#1}{}%
- }%
+ \forest at configured@nodewalk{independent}{inherited}{inherited}{#1}{}%
}
\def\forest at csvlist@getfirst@#1{% assuming that the list is nonempty and finishes with a comma
\forest at csvlist@getfirst@@#1\forest at csvlist@getfirst@@}
@@ -4366,7 +6064,7 @@
\expandafter\forest at csvlist@getfirstrest@\expandafter{\forest at nodewalksort@list}\forest at nodewalksort@cn\forest at nodewalksort@list
\csedef{forest at nodesort@\safeloopn}{\forest at nodewalksort@cn}%
\saferepeat
- \edef\forest at nodesort@sortkey{\forest at nodesort@by}%
+ \forestrget{sort by}\forest at nodesort@sortkey
\forest at sort\forest at nodesort@cmpnodes\forest at nodesort@let#2{1}{#1}%
\def\forest at nodewalksort@sorted{}%
\safeloop
@@ -4454,7 +6152,7 @@
% #2 = max index in list (start with 1)
% #3 = min/max = ascending/descending = </>
% #4 = how many results? 1 = {\forest at nodewalk@minmax at node,}, all={\forest at nodewalk@minmax at nodes}, walk in history={}
- \edef\forest at nodesort@sortkey{\forest at nodesort@by}%
+ \forestrget{sort by}\forest at nodesort@sortkey
\edef\forest at nodewalk@minmax at N{\number\numexpr#2}%
\edef\forest at nodewalk@minmax at n{}%
\edef\forest at nodewalk@minmax at list{#1}%
@@ -4679,7 +6377,7 @@
define long step={descendants breadth-first}{}{\forest at node@foreach at breadthfirst{0}{\forest at nodewalk@makestep}},
define long step={descendants breadth-first reversed}{}{\forest at node@foreach at breadthfirst@reversed{0}{\forest at nodewalk@makestep}},
define long step={level}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{\forest at temp}%
@@ -4687,7 +6385,7 @@
}\forest at marshal
},
define long step={level>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{-1}%
@@ -4695,8 +6393,7 @@
}\forest at marshal
},
define long step={level<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)-1}%
- \show\forest at temp
+ \forestmathtruncatemacro\forest at temp{(#1)-1}%
\ifnum\forest at temp=-1
% special case, as \forest at node@foreach at breadthfirst uses level<0 as a signal for unlimited max level
\ifnum\forestove{level}=0
@@ -4711,7 +6408,7 @@
\fi
},
define long step={level reversed}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4719,7 +6416,7 @@
}\forest at marshal
},
define long step={level reversed>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{-1}%
@@ -4727,7 +6424,7 @@
}\forest at marshal
},
define long step={level reversed<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)-1}%
+ \forestmathtruncatemacro\forest at temp{(#1)-1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4736,7 +6433,7 @@
},
%
define long step={relative level}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{\forest at temp}%
@@ -4744,7 +6441,7 @@
}\forest at marshal
},
define long step={relative level>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{-1}%
@@ -4752,7 +6449,7 @@
}\forest at marshal
},
define long step={relative level<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{\forest at temp}%
@@ -4760,7 +6457,7 @@
}\forest at marshal
},
define long step={relative level reversed}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4768,7 +6465,7 @@
}\forest at marshal
},
define long step={relative level reversed>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{-1}%
@@ -4776,7 +6473,7 @@
}\forest at marshal
},
define long step={relative level reversed<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4783,6 +6480,19 @@
{\noexpand\forest at nodewalk@makestep}%
}\forest at marshal
},
+ define long step={leaves}{}{%
+ \forest at node@foreach{%
+ \ifnum\forestove{n children}=0
+ \forest at nodewalk@makestep
+ \fi
+ }%
+ },
+ define long step={-level}{n args=1,style}{%
+ unique={branch={leaves,{group={repeat={#1}{parent}}}}}
+ },
+ define long step={-level'}{n args=1,style}{%
+ unique={on invalid={fake}{branch={leaves,{group={repeat={#1}{parent}}}}}}
+ },
define long step={children}{}{\forest at node@foreachchild{\forest at nodewalk@makestep}},
define long step={children reversed}{}{\forest at node@foreachchild at reversed{\forest at nodewalk@makestep}},
define long step={current and following siblings}{}{\forest at node@@forselfandfollowingsiblings{\forest at nodewalk@makestep}},
@@ -4867,9 +6577,15 @@
\def\forest at saveandrestoreifcs#1#2{% #1 = the if cs to save before and restore after processing code in #2
\edef\forest at marshal{%
\unexpanded{#2}%
- \ifbool{#1}{\noexpand\setbool{#1}{true}}{\noexpand\setbool{#1}{false}}
+ \ifbool{#1}{\noexpand\setbool{#1}{true}}{\noexpand\setbool{#1}{false}}%
}\forest at marshal
}
+\def\forest at globalsaveandrestoreifcs#1#2{% #1 = the if cs to save before and restore after processing code in #2
+ \edef\forest at marshal{%
+ \unexpanded{#2}%
+ \ifbool{#1}{\global\noexpand\setbool{#1}{true}}{\global\noexpand\setbool{#1}{false}}%
+ }\forest at marshal
+}
\def\forest at saveandrestoretoks#1#2{% #1 = the toks to save before and restore after processing code in #2
\edef\forest at marshal{%
\unexpanded{#2}%
@@ -4884,7 +6600,7 @@
}
\forestset{
save and restore register/.code 2 args={%
- \forest at saveandrestoreregister{filter at ed}{%
+ \forest at saveandrestoreregister{#1}{%
\pgfkeysalso{#2}%
}%
},
@@ -4995,21 +6711,16 @@
replace by''/.code={\forest at replaceby@code{#1}{insert after''}},
sort/.code={%
\eapptotoks\forest at do@dynamics{%
- \noexpand\forest at nodesort
- \noexpand\forest at sort@ascending
- {\forest at cn}%
- {\expandonce{\forest at nodesort@by}}%
+ \def\noexpand\forest at nodesort@sortkey{\forestrv{sort by}}%
+ \noexpand\forest at nodesort\noexpand\forest at sort@ascending{\forest at cn}
}%
},
sort'/.code={%
\eapptotoks\forest at do@dynamics{%
- \noexpand\forest at nodesort
- \noexpand\forest at sort@descending
- {\forest at cn}%
- {\expandonce{\forest at nodesort@by}}%
+ \def\noexpand\forest at nodesort@sortkey{\forestrv{sort by}}%
+ \noexpand\forest at nodesort\noexpand\forest at sort@descending{\forest at cn}
}%
},
- sort by/.store in=\forest at nodesort@by,
}
\def\forest at replaceby@code#1#2{%#1=node spec,#2=insert after['][']
\ifnum\forestove{@parent}=0
@@ -5025,10 +6736,9 @@
}%
\fi
}
-\def\forest at nodesort#1#2#3{% #1 = direction, #2 = parent node, #3 = sort key
+\def\forest at nodesort#1#2{% #1 = direction, #2 = parent node
\ifforestdebugdynamics\forestdebug at dynamics{before sorting children of #2}\fi
- \def\forest at nodesort@sortkey{#3}%
- \forest at fornode{#2}{\forest at nodesort@#1}%
+ \forest at fornode{#2}{\forest at nodesort@#1}%
\ifforestdebugdynamics\forestdebug at dynamics{after sorting children of #2}\fi
}
\def\forest at nodesort@#1{%
@@ -5056,29 +6766,56 @@
\forest at loop
\ifnum\c at pgf@counta<\forest at nodesort@n\relax
\advance\c at pgf@counta 1
- \edef\temp{\csname forest at nodesort@\the\c at pgf@counta\endcsname}%
\forest at node@append{\csname forest at nodesort@\the\c at pgf@counta\endcsname}%
\forest at repeat
}
\def\forest at nodesort@cmpnodes#1#2{%
- \global\let\forest at nodesort@cmpresult\forest at sort@cmp at eq
- \foreach \forest at temp@pgfmath in \forest at nodesort@sortkey {%
- \forest at fornode{\csname forest at nodesort@#1\endcsname}{%
- \pgfmathparse{\forest at temp@pgfmath}\global\let\forest at global@tempa\pgfmathresult}%
- \forest at fornode{\csname forest at nodesort@#2\endcsname}{%
- \pgfmathparse{\forest at temp@pgfmath}\global\let\forest at global@tempb\pgfmathresult}%
- \ifdim\forest at global@tempa pt<\forest at global@tempb pt
- \global\let\forest at nodesort@cmpresult\forest at sort@cmp at lt
- \breakforeach
- \else
- \ifdim\forest at global@tempa pt>\forest at global@tempb pt
- \global\let\forest at nodesort@cmpresult\forest at sort@cmp at gt
- \breakforeach
- \fi
+ \expandafter\forest at nodesort@cmpnodes@\forest at nodesort@sortkey,\forest at END{#1}{#2}%
+}
+\def\forest at nodesort@cmpnodes@#1,#2\forest at END#3#4{%
+ % #1=process ins+arg for this dimension, #2=for next dimensions
+ % #3, #4 = node ids
+ {%
+ \forest at fornode{\csname forest at nodesort@#3\endcsname}{%
+ \forestmathsetmacro\forest at nodesort@resulta{#1}%
+ }%
+ \forest at fornode{\csname forest at nodesort@#4\endcsname}{%
+ \forestmathsetmacro\forest at nodesort@resultb{#1}%
+ }%
+ \ifx\forestmathresulttype\forestmathtype at generic
+ \forest at cmp@error{\forest at nodesort@resulta}{\forest at nodesort@resultb}%
\fi
+ \edef\forest at temp{%
+ \noexpand\forest at nodesort@cmp
+ {\expandonce{\forest at nodesort@resulta}}%
+ {\expandonce{\forest at nodesort@resultb}}%
+ }%
+ \xdef\forest at global@temp{\forest at temp}%
}%
- \forest at nodesort@cmpresult
+ \if=\forest at global@temp
+ \let\forest at next\forest at nodesort@cmpnodes@
+ \else
+ \let\forest at next\forest at nodesort@cmpnodes at finish
+ \fi
+ \ifstrempty{#2}{\let\forest at next\forest at nodesort@cmpnodes at finish}{}%
+ \forest at next#2\forest at END{#3}{#4}%
}
+\def\forest at nodesort@cmpnodes at finish#1\forest at END#2#3{%
+ \let\forest at sort@cmp at result\forest at global@temp
+}
+% \end{macrocode}
+% Usage: |\forest at nodesort@cmp|\meta{first}\meta{second}. Fully expandable. Return |<|, |=| or |>|, as required by |\forest at sort|.
+% \begin{macrocode}
+\def\forest at nodesort@cmp{\csname fRsT at nsc@\forestmathresulttype\endcsname}
+\def\fRsT at nsc@#1{\csname fRsT at nsc@#1\endcsname}
+\def\fRsT at nsc@n#1#2{\ifnum#1<#2 <\else\ifnum#1=#2 =\else>\fi\fi}
+\def\fRsT at nsc@d#1#2{\ifdim#1<#2 <\else\ifdim#1=#2 =\else>\fi\fi}
+\def\fRsT at nsc@P#1#2{\ifdim#1pt<#2pt <\else\ifdim#1pt=#2pt =\else>\fi\fi}
+\def\fRsT at nsc@t#1#2{\csname fRsT at nsc@\pdfstrcmp{#1}{#2}\endcsname}
+\def\fRsT at nsc@T#1#2{\csname fRsT at nsc@\pdfstrcmp{#2}{#1}\endcsname}
+\csdef{fRsT at nsc@-1}{<}
+\csdef{fRsT at nsc@0}{=}
+\csdef{fRsT at nsc@1}{>}
\def\forest at nodesort@let#1#2{%
\csletcs{forest at nodesort@#1}{forest at nodesort@#2}%
}
@@ -5141,10 +6878,17 @@
declare keylist={before computing xy}{},
declare keylist={before drawing tree}{},
declare keylist={delay}{},
- delay n/.style 2 args={if={#1==0}{#2}{delay at n={#1}{#2}}},
- delay at n/.style 2 args={
- if={#1==1}{delay={#2}}{delay={delay at n/.process args={P}{#1-1}{#2}}}
+ delay n/.code 2 args={%
+ \forestmathsetcount\forest at temp@count{#1}%
+ \pgfkeysalso{delay n'={\forest at temp@count}{#2}}%
},
+ delay n'/.code 2 args={
+ \ifnum#1=0
+ \pgfkeysalso{#2}%
+ \else
+ \pgfkeysalso{delay={delay n'/.expand once=\expandafter{\number\numexpr#1-1\relax}{#2}}}%
+ \fi
+ },
if have delayed/.style 2 args={if have delayed'={processing order}{#1}{#2}},
if have delayed'/.code n args=3{%
\forest at havedelayedoptionsfalse
@@ -5732,7 +7476,7 @@
\def\forest at pack@pgfpoint at childsposition#1{%
{%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\forest at fornode{#1}{%
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}%
}%
@@ -5745,7 +7489,7 @@
\def\forest at pack@pgfpoint at positioningrow#1{%
{%
\pgftransformreset
- \pgftransformrotate{#1}%
+ \forest at pgfqtransformrotate{#1}%
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}%
}%
}
@@ -5766,7 +7510,7 @@
{%
\edef\forest at temp@child{\forest at node@nornbarthchildid{\forestove{calign primary child}}}%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\pgfpointtransformed{\pgfqpoint{\forestOve{\forest at temp@child}{l}}{\forestOve{\forest at temp@child}{s}}}%
\pgf at xa=\pgf at x\relax\pgf at ya=\pgf at y\relax
\forest at Pointanchor{\forest at temp@child}{child anchor}%
@@ -5775,7 +7519,7 @@
\advance\pgf at xa-\pgf at x\relax\advance\pgf at ya-\pgf at y\relax
\edef\forest at marshal{%
\noexpand\pgftransformreset
- \noexpand\pgftransformrotate{-\forestove{grow}}%
+ \noexpand\forest at pgfqtransformrotate{-\forestove{grow}}%
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf at xa}{\the\pgf at ya}}%
}\forest at marshal
}%
@@ -5793,7 +7537,7 @@
\edef\forest at temp@firstchild{\forest at node@nornbarthchildid{\forestove{calign primary child}}}%
\edef\forest at temp@secondchild{\forest at node@nornbarthchildid{\forestove{calign secondary child}}}%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\pgfpointtransformed{\pgfqpoint{\forestOve{\forest at temp@firstchild}{l}}{\forestOve{\forest at temp@firstchild}{s}}}%
\pgf at xa=\pgf at x\relax\pgf at ya=\pgf at y\relax
\forest at Pointanchor{\forest at temp@firstchild}{child anchor}%
@@ -5809,7 +7553,7 @@
\advance\pgf at xa-\pgf at x\relax\advance\pgf at ya-\pgf at y\relax
\edef\forest at marshal{%
\noexpand\pgftransformreset
- \noexpand\pgftransformrotate{-\forestove{grow}}%
+ \noexpand\forest at pgfqtransformrotate{-\forestove{grow}}%
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf at xa}{\the\pgf at ya}}%
}\forest at marshal
}%
@@ -5823,6 +7567,10 @@
% angles between node anchors; the version |fixes_edge_angles| calculates the angles between the
% node edges.
% \begin{macrocode}
+\def\forest at edef@strippt#1#2{%
+ \edef#1{#2}%
+ \edef#1{\expandafter\Pgf at geT#1}%
+}
\csdef{forest at calign@fixed angles}{%
\ifnum\forestove{n children}>1
\edef\forest at ca@first at child{\forest at node@nornbarthchildid{\forestove{calign primary child}}}%
@@ -5833,19 +7581,35 @@
\let\forest at ca@second at child\forest at temp
\fi
\forestOget{\forest at ca@first at child}{l}\forest at ca@first at l
+ \edef\forest at ca@first at l{\expandafter\Pgf at geT\forest at ca@first at l}%
\forestOget{\forest at ca@second at child}{l}\forest at ca@second at l
- \pgfmathsetlengthmacro\forest at ca@desired at s@distance{%
- tan(\forestove{calign secondary angle})*\forest at ca@second at l
- -tan(\forestove{calign primary angle})*\forest at ca@first at l
- }%
+ \edef\forest at ca@second at l{\expandafter\Pgf at geT\forest at ca@second at l}%
+ \pgfmathtan@{\forestove{calign secondary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@second at l}%
+ \let\forest at calign@temp\pgfmathresult
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@first at l}%
+ \edef\forest at ca@desired at s@distance{\the\dimexpr
+ \forest at calign@temp pt-\pgfmathresult pt}%
+ % \pgfmathsetlengthmacro\forest at ca@desired at s@distance{%
+ % tan(\forestove{calign secondary angle})*\forest at ca@second at l
+ % -tan(\forestove{calign primary angle})*\forest at ca@first at l
+ % }%
\forestOget{\forest at ca@first at child}{s}\forest at ca@first at s
\forestOget{\forest at ca@second at child}{s}\forest at ca@second at s
- \pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ \edef\forest at ca@actual at s@distance{\the\dimexpr
\forest at ca@second at s-\forest at ca@first at s}%
+ %\pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ % \forest at ca@second at s-\forest at ca@first at s}%
\ifdim\forest at ca@desired at s@distance>\forest at ca@actual at s@distance\relax
\ifdim\forest at ca@actual at s@distance=0pt
- \pgfmathsetlength\pgfutil at tempdima{tan(\forestove{calign primary angle})*\forest at ca@second at l}%
- \pgfmathsetlength\pgfutil at tempdimb{\forest at ca@desired at s@distance/(\forestove{n children}-1)}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@second at l}%
+ \pgfutil at tempdima=\pgfmathresult pt
+ % \pgfmathsetlength\pgfutil at tempdima{tan(\forestove{calign primary angle})*\forest at ca@second at l}%
+ \pgfutil at tempdimb=\dimexpr
+ \forest at ca@desired at s@distance/(\forestove{n children}-1)\relax%
+ %\pgfmathsetlength\pgfutil at tempdimb{\forest at ca@desired at s@distance/(\forestove{n children}-1)}%
\forest at node@foreachchild{%
\forestoeset{s}{\the\pgfutil at tempdima}%
\advance\pgfutil at tempdima\pgfutil at tempdimb
@@ -5852,26 +7616,49 @@
}%
\def\forest at calign@anchor{0pt}%
\else
- \pgfmathsetmacro\forest at ca@ratio{%
- \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetmacro\forest at ca@ratio{%
+ % \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
\forest at node@foreachchild{%
- \pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{s}}%
- \forestolet{s}\forest at temp
+ \forest at edef@strippt\forest at temp{\forestove{s}}%
+ \pgfmathmultiply@{\forest at ca@ratio}{\forest at temp}%
+ \forestoeset{s}{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{s}}%
+ %\forestolet{s}\forest at temp
}%
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@first at l}%
+ \edef\forest at calign@anchor{\the\dimexpr-\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
\fi
\else
\ifdim\forest at ca@desired at s@distance<\forest at ca@actual at s@distance\relax
- \pgfmathsetlengthmacro\forest at ca@ratio{%
- \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetlengthmacro\forest at ca@ratio{%
+ % \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
\forest at node@foreachchild{%
- \pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{l}}%
- \forestolet{l}\forest at temp
+ \forest at edef@strippt\forest at temp{\forestove{l}}%
+ \pgfmathmultiply@{\forest at ca@ratio}{\forest at temp}%
+ \forestoeset{l}{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{l}}%
+ %\forestolet{l}\forest at temp
}%
\forestOget{\forest at ca@first at child}{l}\forest at ca@first at l
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
+ \edef\forest at ca@first at l{\expandafter\Pgf at geT\forest at ca@first at l}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@first at l}%
+ \edef\forest at calign@anchor{\the\dimexpr-\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
\fi
\fi
\forest at calign@s at shift{-\forest at calign@anchor}%
@@ -5897,16 +7684,33 @@
\forest at Pointanchor{\forest at ca@second at child}{child anchor}%
\edef\forest at ca@second at child@anchor at s{\the\pgf at x}%
\edef\forest at ca@second at child@anchor at l{\the\pgf at y}%
- \pgfmathsetlengthmacro\forest at ca@desired at second@edge at s{tan(\forestove{calign secondary angle})*%
- (\forest at ca@second at l-\forest at ca@second at child@anchor at l+\forest at ca@parent at anchor@l)}%
- \pgfmathsetlengthmacro\forest at ca@desired at first@edge at s{tan(\forestove{calign primary angle})*%
- (\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)}
- \pgfmathsetlengthmacro\forest at ca@desired at s@distance{\forest at ca@desired at second@edge at s-\forest at ca@desired at first@edge at s}%
+ \pgfmathtan@{\forestove{calign secondary angle}}%
+ \edef\forest at temp{\the\dimexpr
+ \forest at ca@second at l-\forest at ca@second at child@anchor at l+\forest at ca@parent at anchor@l}%
+ \pgfmathmultiply@{\pgfmathresult}{\expandafter\Pgf at geT\forest at temp}%
+ \edef\forest at ca@desired at second@edge at s{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at ca@desired at second@edge at s{%
+ % tan(\forestove{calign secondary angle})*%
+ % (\forest at ca@second at l-\forest at ca@second at child@anchor at l+\forest at ca@parent at anchor@l)}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \edef\forest at temp{\the\dimexpr
+ \forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l}%
+ \pgfmathmultiply@{\pgfmathresult}{\expandafter\Pgf at geT\forest at temp}%
+ \edef\forest at ca@desired at first@edge at s{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at ca@desired at first@edge at s{%
+ % tan(\forestove{calign primary angle})*%
+ % (\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)}%
+ \edef\forest at ca@desired at s@distance{\the\dimexpr
+ \forest at ca@desired at second@edge at s-\forest at ca@desired at first@edge at s}%
+ %\pgfmathsetlengthmacro\forest at ca@desired at s@distance{\forest at ca@desired at second@edge at s-\forest at ca@desired at first@edge at s}%
\forestOget{\forest at ca@first at child}{s}\forest at ca@first at s
\forestOget{\forest at ca@second at child}{s}\forest at ca@second at s
- \pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ \edef\forest at ca@actual at s@distance{\the\dimexpr
\forest at ca@second at s+\forest at ca@second at child@anchor at s
-\forest at ca@first at s-\forest at ca@first at child@anchor at s}%
+ %\pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ % \forest at ca@second at s+\forest at ca@second at child@anchor at s
+ % -\forest at ca@first at s-\forest at ca@first at child@anchor at s}%
\ifdim\forest at ca@desired at s@distance>\forest at ca@actual at s@distance\relax
\ifdim\forest at ca@actual at s@distance=0pt
\forestoget{n children}\forest at temp@n at children
@@ -5913,48 +7717,90 @@
\forest at node@foreachchild{%
\forest at pointanchor{child anchor}%
\edef\forest at temp@child at anchor@s{\the\pgf at x}%
- \pgfmathsetlengthmacro\forest at temp{%
- \forest at ca@desired at first@edge at s+(\forestove{n}-1)*\forest at ca@desired at s@distance/(\forest at temp@n at children-1)+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
- \forestolet{s}\forest at temp
+ \forestoeset{s}{\the\dimexpr
+ \forest at ca@desired at first@edge at s+\forest at ca@desired at s@distance*(\forestove{n}-1)/(\forest at temp@n at children-1)+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
+ %\pgfmathsetlengthmacro\forest at temp{%
+ % \forest at ca@desired at first@edge at s+(\forestove{n}-1)*\forest at ca@desired at s@distance/(\forest at temp@n at children-1)+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
+ %\forestolet{s}\forest at temp
}%
\def\forest at calign@anchor{0pt}%
\else
- \pgfmathsetmacro\forest at ca@ratio{%
- \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetmacro\forest at ca@ratio{%
+ % \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
\forest at node@foreachchild{%
\forest at pointanchor{child anchor}%
\edef\forest at temp@child at anchor@s{\the\pgf at x}%
- \pgfmathsetlengthmacro\forest at temp{%
- \forest at ca@ratio*(%
- \forestove{s}-\forest at ca@first at s
- +\forest at temp@child at anchor@s-\forest at ca@first at child@anchor at s)%
- +\forest at ca@first at s
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\forest at ca@ratio}%
+ {\expandafter\Pgf at geT\the\dimexpr
+ \forestove{s}-\forest at ca@first at s+%
+ \forest at temp@child at anchor@s-\forest at ca@first at child@anchor at s}%
+ }\forest at marshal
+ \forestoeset{s}{\the\dimexpr\pgfmathresult pt+\forest at ca@first at s
+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
- \forestolet{s}\forest at temp
+ % \pgfmathsetlengthmacro\forest at temp{%
+ % \forest at ca@ratio*(%
+ % \forestove{s}-\forest at ca@first at s
+ % +\forest at temp@child at anchor@s-\forest at ca@first at child@anchor at s)%
+ % +\forest at ca@first at s
+ % +\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
+ % \forestolet{s}\forest at temp
}%
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*(\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)%
- +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
- }%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\pgfmathresult}%
+ {\expandafter\Pgf at geT\the\dimexpr
+ \forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l}%
+ }\forest at marshal
+ \edef\forest at calign@anchor{\the\dimexpr
+ -\pgfmathresult pt+\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s}%
+ % \pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*(\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)%
+ % +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
+ % }%
\fi
\else
\ifdim\forest at ca@desired at s@distance<\forest at ca@actual at s@distance\relax
- \pgfmathsetlengthmacro\forest at ca@ratio{%
- \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetlengthmacro\forest at ca@ratio{%
+ % \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
\forest at node@foreachchild{%
\forest at pointanchor{child anchor}%
\edef\forest at temp@child at anchor@l{\the\pgf at y}%
- \pgfmathsetlengthmacro\forest at temp{%
- \forest at ca@ratio*(%
- \forestove{l}+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)
- -\forest at ca@parent at anchor@l+\forest at temp@child at anchor@l}%
- \forestolet{l}\forest at temp
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\forest at ca@ratio}%
+ {\expandafter\Pgf at geT\the\dimexpr\forestove{l}+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l}%
+ }\forest at marshal
+ \forestoeset{l}{\the\dimexpr
+ \pgfmathresult pt-\forest at ca@parent at anchor@l+\forest at temp@child at anchor@l}%
+ % \pgfmathsetlengthmacro\forest at temp{%
+ % \forest at ca@ratio*(%
+ % \forestove{l}+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)
+ % -\forest at ca@parent at anchor@l+\forest at temp@child at anchor@l}%
+ % \forestolet{l}\forest at temp
}%
\forestOget{\forest at ca@first at child}{l}\forest at ca@first at l
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*(\forest at ca@first at l+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)%
- +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
- }%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\pgfmathresult}%
+ {\expandafter\Pgf at geT\the\dimexpr
+ \forest at ca@first at l+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l}%
+ }\forest at marshal
+ \edef\forest at calign@anchor{\the\dimexpr
+ -\pgfmathresult pt+\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s}%
+ % \pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*(\forest at ca@first at l+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)%
+ % +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
+ % }%
\fi
\fi
\forest at calign@s at shift{-\forest at calign@anchor}%
@@ -6030,7 +7876,7 @@
% \begin{macrocode}
\pgfgettransform\forest at temp@transform
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
% \end{macrocode}
% Get the child's (cached) edge, translate it by the child's position,
% and add it to the path holding all edges. Also add the edge from parent to the child to the path.
@@ -6662,8 +8508,12 @@
}\forest at marshal
}
\def\forest at node@computeabsolutepositions@#1#2#3{%
- \pgfpointadd{\pgfpoint{#1}{#2}}{%
- \pgfpointadd{\pgfpolar{#3}{\forestove{l}}}{\pgfpolar{90 + #3}{\forestove{s}}}}%
+ \pgfpointadd
+ {\pgfqpoint{#1}{#2}}%
+ {\pgfpointadd
+ {\pgfqpointpolar{#3}{\forestove{l}}}%
+ {\pgfqpointpolar{\numexpr 90+#3\relax}{\forestove{s}}}%
+ }%
\pgfgetlastxy\forest at temp@x\forest at temp@y
\forestolet{x}\forest at temp@x
\forestolet{y}\forest at temp@y
@@ -6835,7 +8685,7 @@
\newdimen\forest at ys
\def\forest at setupgrowline#1{%
\edef\forest at grow{#1}%
- \pgfpointpolar\forest at grow{1pt}%
+ \pgfqpointpolar{\forest at grow}{1pt}%
\forest at xg=\pgf at x
\forest at yg=\pgf at y
\forest at xs=-\pgf at y
@@ -7237,6 +9087,10 @@
\let\forest at previous@py\forest at py
}
% \end{macrocode}
+% Patch for speed: no need to call |\pgfmathparse| here.
+% \begin{macrocode}
+\patchcmd{\pgfpointintersectionoflines}{\pgfpoint}{\pgfqpoint}{}{}
+% \end{macrocode}
%
% \subsection{Get tight edge of path}
%
@@ -7659,7 +9513,11 @@
\pgf at x=0pt
\fi
\fi
- \csname pgfmathatan2\endcsname{\pgf at x}{\pgf at y}%
+ \edef\forest at marshal{%
+ \noexpand\pgfmathatantwo@
+ {\expandafter\Pgf at geT\the\pgf at x}%
+ {\expandafter\Pgf at geT\the\pgf at y}%
+ }\forest at marshal
\let\forest at current@atan\pgfmathresult
\ifx\forest at last@atan\relax
% \end{macrocode}
@@ -7722,7 +9580,7 @@
}%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@path
}%
\pgfsyssoftpath at getcurrentpath#2%
@@ -7735,7 +9593,7 @@
}%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@path
}%
\pgfsyssoftpath at getcurrentpath#2%
@@ -7752,13 +9610,13 @@
}%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@negpath
}%
\pgfsyssoftpath at getcurrentpath#2%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@pospath
}%
\pgfsyssoftpath at getcurrentpath#3%
@@ -8001,7 +9859,7 @@
\def\forest at path@getboundingrectangle at ls#1#2{%
{%
\pgftransformreset
- \pgftransformrotate{-(#2)}%
+ \forest at pgfqtransformrotate{-#2}%
\forest at pgfpathtransformed#1%
}%
\pgfsyssoftpath at getcurrentpath\forest at gbr@rotatedpath
@@ -8026,6 +9884,20 @@
\ifdim#2>\pgf at yb\relax\pgf at yb=#2 \fi
}
% \end{macrocode}
+% Hack: create our own version of |pgf|'s |\pgftransformrotate| which does not call |\pgfmathparse|. Nothing really bad happens if patch fails. We're just a bit slower.
+% \begin{macrocode}
+\let\forest at pgfqtransformrotate\pgftransformrotate
+\let\forest at pgftransformcm\pgftransformcm
+\let\forest at pgf@transformcm\pgf at transformcm
+\patchcmd{\forest at pgfqtransformrotate}{\pgfmathparse{#1}}{\edef\pgfmathresult{\number\numexpr#1}}{}{}
+\patchcmd{\forest at pgfqtransformrotate}{\pgftransformcm}{\forest at pgftransformcm}{}{}
+\patchcmd{\forest at pgftransformcm}{\pgf at transformcm}{\forest at pgf@transformcm}{}{}
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\def\forest at pgf@transformcm at setlength#1#2{#1=#2pt}
+% \end{macrocode}
%
% \section{The outer UI}
%
@@ -8053,10 +9925,11 @@
}%
}{}%
}
+\newread\forest at copy@in
+\newwrite\forest at copy@out
\def\forest at file@copy@#1#2{%
- \newread\forest at copy@in
+ \begingroup
\openin\forest at copy@in=#1
- \newwrite\forest at copy@out
\immediate\openout\forest at copy@out#2
\endlinechar-1
\loop
@@ -8066,6 +9939,7 @@
\repeat
\immediate\closeout\forest at copy@out
\closein\forest at copy@in
+ \endgroup
}
\newif\ifforest at external@optimize@
\forest at external@optimize at true
@@ -8137,11 +10011,15 @@
\forest at next{#3}%
}
\def\forest at config#1{%
- \def\forest at stages{stages}%
+ \forest at defstages{stages}%
\forestset{@config/.cd,#1}%
}
+\def\forest at defstages#1{%
+ \def\forest at stages{#1}%
+}
\forestset{@config/.cd,
- stages/.store in=\forest at stages,
+ %stages/.store in=\forest at stages,
+ stages/.code={\forest at defstages{#1}},
.unknown/.code={\PackageError{forest}{Unknown config option for forest environment/command.}{In Forest v2.0.0 and v2.0.1, this (parenthesized) argument accepted the definition of style stages for the current forest environment/macro. Since v2.0.2, you should write "\string\begin{forest}(stages={...})...\string\end{forest}", or "\string\Forest(stages={...}){...}" instead.}}
}
\def\forest at group@env#1{{\forest at env{#1}}}
@@ -8413,9 +10291,9 @@
\pgfkeysvalueof{/pgf/inner xsep},\pgfkeysvalueof{/pgf/outer xsep}%
}
{
- l sep={\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}},
+ l sep'/.expanded={\the\dimexpr\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}},
l={l_sep()+abs(max_y()-min_y())+2*\pgfkeysvalueof{/pgf/outer ysep}},
- s sep={2*\pgfkeysvalueof{/pgf/inner xsep}}
+ s sep'/.expanded={\the\dimexpr \pgfkeysvalueof{/pgf/inner xsep}*2}
}
{l sep,l,s sep}
% \end{macrocode}
@@ -8437,11 +10315,11 @@
\forest at forestcs@resetxy},
anchor/.code={\forest at forestcs@anchor{#1}},
l/.code={%
- \pgfmathsetlengthmacro\forest at forestcs@l{#1}%
+ \forestmathsetlengthmacro\forest at forestcs@l{#1}%
\forest at forestcs@ls
},
s/.code={%
- \pgfmathsetlengthmacro\forest at forestcs@s{#1}%
+ \forestmathsetlengthmacro\forest at forestcs@s{#1}%
\forest at forestcs@ls
},
.unknown/.code={%
@@ -8456,8 +10334,8 @@
}
\def\forest at forestcs@resetxy{%
\ifnum\forest at cn=0 \forest at cs@invalidnodeerror\fi
- \global\pgf at x\forestove{x}%
- \global\pgf at y\forestove{y}%
+ \global\pgf at x\forestove{x}\relax
+ \global\pgf at y\forestove{y}\relax
}
\def\forest at forestcs@ls{%
\ifdefined\forest at forestcs@l
@@ -8464,8 +10342,8 @@
\ifdefined\forest at forestcs@s
{%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
- \pgfpointtransformed{\pgfpoint{\forest at forestcs@l}{\forest at forestcs@s}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
+ \pgfpointtransformed{\pgfqpoint{\forest at forestcs@l}{\forest at forestcs@s}}%
}%
\global\advance\pgf at x\forestove{x}%
\global\advance\pgf at y\forestove{y}%
@@ -8590,10 +10468,18 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{children first}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children first}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children first}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children first}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{first}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{first}{\forest at referencednodeid}%
@@ -8602,14 +10488,26 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent first}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent first}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent first}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent last}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent last}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent last}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent last}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{last}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{last}{\forest at referencednodeid}%
@@ -8618,14 +10516,26 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children last}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children last}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children last}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{children'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{children first'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children first'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children first'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children first'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{first'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{first'}{\forest at referencednodeid}%
@@ -8634,14 +10544,26 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent first'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent first'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent first'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent last'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent last'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent last'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent last'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{last'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{last'}{\forest at referencednodeid}%
@@ -8650,6 +10572,10 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children last'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children last'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children last'}{\forest at referencednodeid}%
+}
% \end{macrocode}
% The driver. The result is being passed around in |\forest at temp@anchor|.
% \begin{macrocode}
@@ -8688,10 +10614,20 @@
\forest at anchor@isbordertrue
\edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}}%
}
+\csdef{forest at anchor@@-children'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor{\number\numexpr 180+\forestove{grow}-\forestove{rotate}}%
+}
\csdef{forest at anchor@@parent'}{%
\forest at anchor@isbordertrue
- \edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@anchor{\number\numexpr\forest at temp@grow-\forestove{rotate}+180}%
}
+\csdef{forest at anchor@@-parent'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@anchor{\number\numexpr\forest at temp@grow-\forestove{rotate}}%
+}
\csdef{forest at anchor@@first'}{%
\forest at anchor@isbordertrue
\edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
@@ -8702,34 +10638,72 @@
}
\csdef{forest at anchor@@parent first'}{%
\forest at anchor@isbordertrue
- \edef\forest at temp@anchor at parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
- \edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}+180}%
+ \edef\forest at temp@anchor at first{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 -\else+\fi90}%
\forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at first}\forest at temp@anchor
}
+\csdef{forest at anchor@@-parent first'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}}%
+ \edef\forest at temp@anchor at first{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 -\else+\fi90}%
+ \forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at first}\forest at temp@anchor
+}
\csdef{forest at anchor@@parent last'}{%
\forest at anchor@isbordertrue
- \edef\forest at temp@anchor at parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
- \edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}+180}%
+ \edef\forest at temp@anchor at last{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 +\else-\fi90}%
\forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at last}\forest at temp@anchor
}
+\csdef{forest at anchor@@-parent last'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}}%
+ \edef\forest at temp@anchor at last{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 +\else-\fi90}%
+ \forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at last}\forest at temp@anchor
+}
\csdef{forest at anchor@@children first'}{%
\forest at anchor@isbordertrue
\edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
\forest at getaverageangle{\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at first}\forest at temp@anchor
}
+\csdef{forest at anchor@@-children first'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
+ \forest at getaverageangle{180+\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at first}\forest at temp@anchor
+}
\csdef{forest at anchor@@children last'}{%
\forest at anchor@isbordertrue
\edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
\forest at getaverageangle{\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at last}\forest at temp@anchor
}
+\csdef{forest at anchor@@-children last'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
+ \forest at getaverageangle{180+\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at last}\forest at temp@anchor
+}
\csdef{forest at anchor@@children}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@children'}%
}
+\csdef{forest at anchor@@-children}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-children'}%
+}
\csdef{forest at anchor@@parent}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@parent'}%
}
+\csdef{forest at anchor@@-parent}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-parent'}%
+}
\csdef{forest at anchor@@first}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@first'}%
@@ -8742,18 +10716,34 @@
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@parent first'}%
}
+\csdef{forest at anchor@@-parent first}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-parent first'}%
+}
\csdef{forest at anchor@@parent last}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@parent last'}%
}
+\csdef{forest at anchor@@-parent last}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-parent last'}%
+}
\csdef{forest at anchor@@children first}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@children first'}%
}
+\csdef{forest at anchor@@-children first}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-children first'}%
+}
\csdef{forest at anchor@@children last}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@children last'}%
}
+\csdef{forest at anchor@@-children last}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-children last'}%
+}
% \end{macrocode}
% This macro computes the "average" angle of |#1| and |#2| and stores in into |#3|.
% The angle computed is the geometrically "closer" one. The formula is
@@ -8761,32 +10751,42 @@
% \begin{macrocode}
\def\forest at getaverageangle#1#2#3{%
\edef\forest at temp{\number\numexpr #1-#2+540}%
- \pgfmathMod{\forest at temp}{360}\pgfmathtruncatemacro\pgfmathresult{\pgfmathresult}
- \edef\forest at temp{360+#2+((\pgfmathresult-180)/2)}%
- \pgfmathMod{\forest at temp}{360}\pgfmathtruncatemacro#3{\pgfmathresult}%
+ \expandafter\pgfmathMod@\expandafter{\forest at temp}{360}%
+ \forest at truncatepgfmathresult
+ \edef\forest at temp{\number\numexpr 360+#2+((\pgfmathresult-180)/2)}%
+ \expandafter\pgfmathMod@\expandafter{\forest at temp}{360}%
+ \forest at truncatepgfmathresult
+ \let#3\pgfmathresult
}
+\def\forest at truncatepgfmathresult{%
+ \afterassignment\forest at gobbletoEND
+ \forest at temp@count=\pgfmathresult\forest at END
+ \def\pgfmathresult{\the\forest at temp@count}%
+}
+\def\forest at gobbletoEND#1\forest at END{}
% \end{macrocode}
% The first macro changes border anchor to compass anchor. The second one does this only if the node shape allows it.
% \begin{macrocode}
\def\forest at anchor@border at to@compass{%
- \ifforest at anchor@isborder
+ \ifforest at anchor@isborder % snap to 45 deg, to range 0-360
\ifforest at anchor@snapbordertocompass
\forest at anchor@snap at border@to at compass
- \else
- \pgfmathMod{\forest at temp@anchor}{360}%
- \pgfmathtruncatemacro\forest at temp@anchor{\pgfmathresult}%
+ \else % to range 0-360
+ \pgfmathMod@{\forest at temp@anchor}{360}%
+ \forest at truncatepgfmathresult
+ \let\forest at temp@anchor\pgfmathresult
\fi
- \ifforest at anchor@forwardtotikz
- \ifcsname pgf at anchor%
- @\csname pgf at sh@ns@\pgfreferencednodename\endcsname
- @\csname forest at compass@\forest at temp@anchor\endcsname
- \endcsname
+ \ifforest at anchor@snapbordertocompass
+ \ifforest at anchor@forwardtotikz
+ \ifcsname pgf at anchor%
+ @\csname pgf at sh@ns@\pgfreferencednodename\endcsname
+ @\csname forest at compass@\forest at temp@anchor\endcsname
+ \endcsname
+ \letcs\forest at temp@anchor{forest at compass@\forest at temp@anchor}%
+ \fi
+ \else
\letcs\forest at temp@anchor{forest at compass@\forest at temp@anchor}%
\fi
- \else
- \ifforest at anchor@snapbordertocompass
- \letcs\forest at temp@anchor{forest at compass@\forest at temp@anchor}%
- \fi
\fi
\fi
}
@@ -8803,11 +10803,12 @@
% This macro approximates an angle (stored in |\forest at temp@anchor|) with a compass direction (stores it in the same macro).
% \begin{macrocode}
\def\forest at anchor@snap at border@to at compass{%
- \pgfmathMod{\forest at temp@anchor}{360}%
- \pgfmathdivide{\pgfmathresult}{45}%
- \pgfmathround{\pgfmathresult}%
- \pgfmathmultiply{\pgfmathresult}{45}%
- \pgfmathtruncatemacro\forest at temp@anchor{\pgfmathresult}%
+ \pgfmathMod@{\forest at temp@anchor}{360}%
+ \pgfmathdivide@{\pgfmathresult}{45}%
+ \pgfmathround@{\pgfmathresult}%
+ \pgfmathmultiply@{\pgfmathresult}{45}%
+ \forest at truncatepgfmathresult
+ \let\forest at temp@anchor\pgfmathresult
}
% \end{macrocode}
% This macro forwards the resulting anchor to \TikZ;.
@@ -8840,34 +10841,32 @@
%
% This macro sets up |\pgf at x| and |\pgf at y| to the given anchor's coordinates, within the node's coordinate system. It works even before the node was positioned. If the anchor is empty, i.e.\ if is the implicit border anchor, we return the coordinates for the center.
% \begin{macrocode}
+\def\forest at pointanchor#1{% #1 = anchor
+ \forest at Pointanchor{\forest at cn}{#1}%
+}
\def\forest at Pointanchor#1#2{% #1 = node id, #2 = anchor
- {%
- \def\forest at pa@temp at name{name}%
- \forestOifdefined{#1}{@box}{%
- \forestOget{#1}{@box}\forest at temp
- \ifdefempty\forest at temp{}{%
- \def\forest at pa@temp at name{later at name}%
+ \def\forest at pa@temp at name{name}%
+ \forestOifdefined{#1}{@box}{%
+ \forestOget{#1}{@box}\forest at temp
+ \ifdefempty\forest at temp{}{%
+ \def\forest at pa@temp at name{later at name}%
+ }%
+ }{}%
+ \setbox0\hbox{%
+ \begin{pgfpicture}% this is expensive: so that's why caching
+ \if\relax\forestOve{#1}{#2}\relax
+ \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{center}%
+ \else
+ \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{\forestOve{#1}{#2}}%
+ \fi
+ \xdef\forest at global@marshal{%
+ \noexpand\global\noexpand\pgf at x=\the\pgf at x\relax
+ \noexpand\global\noexpand\pgf at y=\the\pgf at y\relax\relax
}%
- }{}%
- \setbox0\hbox{%
- \begin{pgfpicture}%
- \if\relax\forestOve{#1}{#2}\relax
- \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{center}%
- \else
- \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{\forestOve{#1}{#2}}%
- \fi
- \xdef\forest at global@marshal{%
- \noexpand\global\noexpand\pgf at x=\the\pgf at x\relax
- \noexpand\global\noexpand\pgf at y=\the\pgf at y
- }%
- \end{pgfpicture}%
- }%
+ \end{pgfpicture}%
}%
- \forest at global@marshal
+ \forest at global@marshal
}
-\def\forest at pointanchor#1{% #1 = anchor
- \forest at Pointanchor{\forest at cn}{#1}%
-}
% \end{macrocode}
%
% \section{Compatibility with previous versions}
Modified: trunk/Master/texmf-dist/tex/latex/forest/forest-compat.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/forest/forest-compat.sty 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/tex/latex/forest/forest-compat.sty 2016-12-06 00:28:11 UTC (rev 42640)
@@ -3,7 +3,7 @@
% forest-index.dtx
%% `forest-compat' defines a compatibility layer of package `forest'.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -23,7 +23,7 @@
%% constituting the package see main source file of the package,
%% `forest.dtx', or the derived `forest.sty'.
-\ProvidesPackage{forest-compat}
+\ProvidesPackage{forest-compat}[2016/12/05]
\def\forest at deprecated#1{%
\PackageWarning{forest}{Compatibility mode for #1}%
@@ -31,7 +31,7 @@
\forestset{@@deprecated/.code={\forest at deprecated{#1}}}
\def\forestcompat#1{\pgfqkeys{/forest/@compat}{#1}}
\forestcompat{
- silent/.style={\def\forest at deprecated##1{}},
+ silent/.code={\def\forest at deprecated##1{}},
%%% begin listing region: compat_keys
most/.style={1.0-most},
all/.style={1.0-all},
@@ -38,7 +38,8 @@
none/.style={},
1.0-most/.style={
1.0-triangle,1.0-linear,1.0-nodewalk,1.0-ancestors,
- 1.0-fittotree,1.0-for,1.0-forall
+ 1.0-fittotree,1.0-for,1.0-forall,
+ 2.0.2-most,
},
1.0-all/.style={
1.0-most,
@@ -45,9 +46,20 @@
1.0-forstep,1.0-rotate,1.0-stages,1.0-name,
2.0.2-all,
},
+ 2.0.2-most/.style={
+ 2.0-most,
+ },
2.0.2-all/.style={
2.0.2-delayn,2.0.2-wrapnpgfmathargs,
+ 2.0-all,
},
+ 2.0-most/.style={},
+ 2.0-all/.style={
+ 2.0-most,
+ 2.0-delayn,
+ 2.0-edges,
+ },
+ 2.0-edges/.style={2.0-anchors,2.0-forkededge,2.0-folder},
%%% end listing region: compat_keys
1.0-triangle/.style={
/forest/triangle/.style={
@@ -106,14 +118,9 @@
},
1.0-forstep/.code={%
\def\forest at forstepwrapper##1##2{%
- \def\forest at nodewalk@config at everystep@method{independent}%
- \def\forest at nodewalk@config at history@method{independent}%
- \edef\forest at marshal{%
- \def\noexpand\forest at nodewalk@config at oninvalid{compatfake}%
- \unexpanded{\forest at Nodewalk{##1}{##2}}%
- \def\noexpand\forest at cn{\forest at cn}%
- \def\noexpand\forest at nodewalk@config at oninvalid{\forest at nodewalk@config at oninvalid}%
- }\forest at marshal
+ \forest at forthis{%
+ \forest at configured@nodewalk{independent}{independent}{compatfake}{##1}{##2}%
+ }%
}%
\def\forest at relatednode@option at compat@ignoreinvalidsteps##1{%
\forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
@@ -172,11 +179,12 @@
},
2.0.2-delayn/.style={
/forest/delay at n/.style 2 args={
- @@deprecated={propagator "delay n" (it introduces two levels of hash doubling)},
+ @@deprecated={propagator "delay n" (it introduces two levels of hash doubling reevaluates the first argument (the desired number of cycles) at every cycle)},
if={##1==1}{delay={##2}}{delay={delay at n/.wrap pgfmath arg={{####1}{##2}}{##1-1}}}
},
+ 2.0-delayn/.style={}, % this key would patch the same thing!
},
- 2.0.2-wrapnpgfmathargs/.code={
+ 2.0.2-wrapnpgfmathargs/.code={%
\def\forest at wrap@pgfmath at args@@@wrapandpasson{%
\forest at deprecated{handler "wrap n pgfmath args" (it introduces two levels of hash doubling)}%
\expandafter\expandafter\expandafter\def
@@ -186,5 +194,58 @@
\expandafter\pgfkeysalso\expandafter{\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{\forest at wrapped}}%
}%
},
+ 2.0-delayn/.style={
+ /forest/delay n/.style 2 args={
+ @@deprecated={propagator "delay n" (it reevaluates the first argument (the desired number of cycles) at every cycle)},
+ if={##1==0}{##2}{delay at n={##1}{##2}}
+ },
+ /forest/delay at n/.style 2 args={
+ if={##1==1}{delay={##2}}{delay={delay at n/.process={P}{##1-1}{##2}}}
+ },
+ },
+ 2.0-anchors/.code={%
+ \csdef{forest at anchor@@parent'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
+ }
+ \csdef{forest at anchor@@parent first'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor at parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
+ \edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
+ \forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at first}\forest at temp@anchor
+ }
+ \csdef{forest at anchor@@parent last'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor at parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
+ \edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
+ \forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at last}\forest at temp@anchor
+ }
+ },
+ 2.0-forkededge/.code={%
+ \forest at iflibraryloaded{edges}{%
+ \forestset{
+ forked edge/.style={
+ edge={rotate/.pgfmath=grow()},
+ edge path'={(!u.parent anchor) -- ++(\forestoption{fork sep},0) |- (.child anchor)},
+ },
+ forked edges/.style={
+ for tree={parent anchor=children},
+ for descendants={child anchor=parent,forked edge}
+ },
+ }%
+ }{%
+ \appto\forest at compat@libraries at edges{\forestcompat{2.0-forkededge}}%
+ }%
+ },
+ 2.0-folder/.code={%
+ \forest at iflibraryloaded{edges}{%
+ \expandafter\patchcmd\csname @pgfk@/forest/folder/. at cmd\endcsname
+ {parent anchor=-children last}{parent anchor=parent last}{}{}%
+ \expandafter\patchcmd\csname @pgfk@/forest/folder/. at cmd\endcsname
+ {edge={rotate/.option=!parent.grow},}{edge={rotate/.pgfmath=grow()}}{}{}%
+ }{%
+ \appto\forest at compat@libraries at edges{\forestcompat{2.0-folder}}%
+ }%
+ },
}
\expandafter\forestcompat\expandafter{\forest at compat}
Modified: trunk/Master/texmf-dist/tex/latex/forest/forest-doc.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/forest/forest-doc.sty 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/tex/latex/forest/forest-doc.sty 2016-12-06 00:28:11 UTC (rev 42640)
@@ -1,7 +1,7 @@
%% forest-doc.sty
%% `forest-doc.sty` is an auxiliary package needed to compile the documentation of package `forest`.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -31,7 +31,7 @@
basicstyle=\small\ttfamily,basewidth=0.51em,boxpos=c,pointstyle=\pstyle,moredelim=[is][\pstyle]{~}{~}}
%\lst at InstallKeywords{p}{point}{pointstyle}\relax{keywordstyle}{}ld
\def\pstyle{\color{darkgreen}}
-\def\itemnosep{\vspace{-1.4ex}}
+\newcommand\itemnosep[1][0pt]{\vspace{\the\dimexpr-1.4ex+#1}}
\lstset{
rangebeginprefix=\ \ \%\%\%\ begin\ listing\ region:\ ,
rangebeginsuffix=,
@@ -230,8 +230,10 @@
\@Repeat{#1}{#2}#2%
}
\def\spaces#1{\Repeat{#1}\space}
-
+\RequirePackage{dingbat}
+
+
%%% Local Variables:
%%% mode: latex
%%% fill-column: 100
Modified: trunk/Master/texmf-dist/tex/latex/forest/forest-index.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/forest/forest-index.sty 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/tex/latex/forest/forest-index.sty 2016-12-06 00:28:11 UTC (rev 42640)
@@ -8,7 +8,7 @@
%%
%% `forest-index' is an indexing system for the documentation of package `forest', using the package itself.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -42,10 +42,8 @@
{\let\forestindex at resolvekey\forestindex at resolvekey@shortorlong}%
\forestindex at index{example}{#1}{#3}}
\DeclareDocumentCommand\indexitem{D(){} O{} t> m}{%
- \IfBooleanTF{#3}
- {\let\forestindex at resolvekey\forestindex at resolvekey@long}
- {\let\forestindex at resolvekey\forestindex at resolvekey@shortorlong}%
- \forestindex at index{definition}{default={#1},print format=item,#2}{#4}}
+ \let\forestindex at resolvekey\forestindex at resolvekey@long
+ \forestindex at index{definition}{default={#1},#2,print format+=item}{#4}}
\DeclareDocumentCommand\indexset{O{} t> m}{%
\IfBooleanTF{#2}
{\let\forestindex at resolvekey\forestindex at resolvekey@long}
@@ -58,15 +56,24 @@
\forestindex at index{#1}{#2}{#4}%
}
\def\forestindex at index#1#2#3{%
- \forcsvlist{\forestindex at forkey{#1}{#2}}{#3}%
+ {\forcsvlist{\forestindex at forkey{#1}{#2}}{#3}}%
}
\def\forestindex at forkey#1#2#3{%
\forestindex at resolvekey{#3}%
- \forestset{@index/.process args={__o}{#1}{#2}{\forestindex at fullkey}}%
+ %\forestset{@index/.process={__o}{#1}{#2}{\forestindex at fullkey}}
+ \edef\forest at marshal{%
+ \noexpand\forestindex at index@{%
+ {\unexpanded{#1}}%
+ {\unexpanded{#2}}%
+ {\expandonce{\forestindex at fullkey}}%
+ }%
+ }\forest at marshal
}
+\def\forestindex at index@#1{\forestset{@index/.process={__o}#1}}
\forestset{
declare boolean register=print,
declare boolean register=index,
+ declare boolean register=short, short,
declare toks={key}{},
declare toks={argument}{},
declare toks={index key}{},
@@ -99,10 +106,11 @@
if n=0{
content/.option=key,
}{
- content/.wrap 2 pgfmath args={##1>##2}{content("!parent")}{key},
+ content/.process={OOw2} {!parent.content} {key} {##1>##2},
}
}{},
for root'={
+ if strequal/.process={O}{!root.name}{@unknown}{TeX=\global\forest at memoizing@ok at false}{},
for tree={
print form/.option=key,
index key/.option=key,
@@ -113,7 +121,7 @@
every index begin,
#1,
},
- for reverse={ancestors}{on invalid={fake}{@@index/\forestoption{name}/.try}},
+ for reverse={current and ancestors}{on invalid={fake}{@@index/\forestoption{name}/.try}},
if index entry type={definition}{}{%
on invalid={fake}{@@index/\forestoption{name}/.try},
},
@@ -125,11 +133,11 @@
if index entry type={definition}{save at foridx}{},
},
stage={},
- if={index()||print()}{
+ if index={
index at hypertarget/.expanded={.\forestoption{index key}},
for descendants={
- index at hypertarget/.wrap 2 pgfmath args={##1.##2}%
- {index at hypertarget("!parent")}{index_key},
+ index at hypertarget/.process= {OOw2}
+ {!parent.index at hypertarget} {index key} {##1.##2},
},
}{},
if index={
@@ -164,11 +172,11 @@
},
},
temptoksa={},
- result={},
+ result'={},
if n children=0{tempboola}{not tempboola},
where index form={}{}{
- if tempboola={temptoksd/.expanded={\noexpand\protect\noexpand\hypertarget{%
- \forestoption{index at hypertarget}}{}}}{temptoksd={}},
+ temptoksd/.expanded={\noexpand\protect\noexpand\hypertarget{%
+ \forestoption{index at hypertarget}}{}},
result+/.expanded={%
\forestregister{temptoksa}%
\forestoption{index key}%
@@ -180,7 +188,7 @@
temptoksb={},
},
result+/.expanded={|indexpagenumber\forestregister{index entry type}},
- TeX/.expanded={\noexpand\forestindex at LaTeX@index{\forestregister{result}}},
+ TeX and memoize/.expanded={\noexpand\forestindex at LaTeX@index{\forestregister{result}}},
},
endgroup
}{},
@@ -192,7 +200,7 @@
process keylist'={print format}{current},
print form/.register=result,
},
- for first leaf'={TeX={\forestoption{print form}}},
+ for first leaf'={TeX and memoize/.expanded={\forestoption{print form}}},
endgroup,
}{},
}
@@ -216,8 +224,8 @@
name'/.option=key,
content={#1},
}{
- name'/.wrap 2 pgfmath args={##1>##2}{name("!parent")}{key},
- content/.wrap pgfmath arg={##1>#1}{content("!parent")},
+ name'/.process={OOw2} {!parent.name} {key} {##1>##2},
+ content/.process={Ow1} {!parent.content} {##1>#1},
},
}
},
@@ -227,29 +235,33 @@
Autoforward register={set}{##1},
save at session/.style={@@index/\forestoption{name}/.global style/.register=set},
save at foridx/.style={
- if={strequal(name("!root"),"@unknown")}{}{
+ if strequal/.process={O}{!root.name}{@unknown}{}{
if set={}{}{
- TeX={%
- \immediate\write\forestindex at out{%
- \string\indexloadsettings{\forestoption{name}}{\forestregister{set}}%
+ TeX and memoize/.expanded={%
+ \noexpand\immediate\noexpand\write\noexpand\forestindex at out{%
+ \noexpand\string\noexpand\indexloadsettings\noexpand\unexpanded{{\forestoption{name}}{\forestregister{set}}}%
}%
},
},
- if={strequal(key(),content())}{}{
- TeX={%
- \immediate\write\forestindex at out{%
- \string\indexdefineshortkey{\forestoption{key}}{\forestoption{content}}%
+ },
+ if key/.process={O}{content} {} {%
+ if short={
+ TeX and memoize/.expanded={%
+ \noexpand\immediate\noexpand\write\noexpand\forestindex at out{%
+ \noexpand\string\noexpand\indexdefineshortkey\noexpand\unexpanded{{\forestoption{key}}{\forestoption{content}}}%
}%
- }
+ }{}%
}
}
- },
+ }
}
\def\indexloadsettings#1#2{%
\pgfkeysifdefined{/forest/@@index/#1/. at cmd}{%
\forestindex at loadsettings@warning{#1}%
}{}%
- \forestset{@@index/#1/.global style={#2}}%
+ % #s in #2 are doubled; the following \def removes one layer of doubling
+ \def\forest at temp{#2}%
+ \forestset{@@index/#1/.global style/.expand once=\forest at temp}%
}
\def\forestindex at loadsettings@warning#1{%
\PackageWarning{forest-index}{Forest index key "#1" was configured more than once!
@@ -304,8 +316,8 @@
normal color/.initial=blue,
definition color/.initial=red,
example color/.initial=darkgreen,
- print in color/.style={if stage={print}{result=\protect\textcolor{%
- \pgfkeysvalueof{/forest/#1 color}}{##1}}{}},
+ print in color/.style={if stage={print}{result/.expanded=\noexpand\protect\noexpand\textcolor{%
+ \pgfkeysvalueof{/forest/#1 color}}{\unexpanded{##1}}}{}},
print in color/.default=\forestregister{index entry type},
hyper/.style={
if stage={index}{}{
@@ -340,9 +352,10 @@
\forestset{
declare toks register=default,
default={},
- item/.style={result/.wrap 4 pgfmath args={%
- \item[,##2,##3]{##4}%
- }{}{default}{print_form("!parent")}{result},
+ item/.style={
+ result/.process= {_RORw4}
+ {} {default} {!parent.print form} {result}
+ {\item[,##2,##3]{##4}},
},
}
\pgfkeys{/handlers/.global style/.code=\pgfkeys{\pgfkeyscurrentpath/.global code=\pgfkeysalso{#1}}}
@@ -359,9 +372,84 @@
\pgfkeys at temptoks{#2}\expandafter\xdef\csname pgfk@#1\endcsname{\the\pgfkeys at temptoks}%
}
\forestset{
+ % unlike pgfmath function strequal, |if strequal| does not expand the compared args!
+ if strequal/.code n args={4}{\ifstrequal{#1}{#2}{\pgfkeysalso{#3}}{\pgfkeysalso{#4}}},
+}
+\forestset{
begingroup/.code={\begingroup},
endgroup/.code={\endgroup},
}
+\newtoks\forest at memo@key
+\newtoks\forest at memo
+\newif\ifforest at memoizing@now@
+\newif\ifforest at memoizing@ok@
+\newif\ifforest at execandmemoize@
+\def\forest at memoize#1{% #1 = \cs
+ \cslet{forest at memo@orig@\string#1}#1%
+ \def#1##1{%
+ \ifforest at memoizing@now@
+ \forest at globalsaveandrestoreifcs{forest at execandmemoize@}{%
+ \global\forest at execandmemoize@false
+ \csname forest at memo@orig@\string#1\endcsname{##1}%
+ }%
+ \else
+ \expandafter\global\expandafter\forest at memo@key\expandafter{\detokenize{forest at memo@#1{##1}}}%
+ \ifcsname\the\forest at memo@key\endcsname
+ \@escapeifif{\csname\the\forest at memo@key\endcsname}%
+ \else
+ \@escapeifif{%
+ \global\forest at memo{}%
+ \global\forest at memoizing@ok at true
+ \global\forest at memoizing@now at true
+ \global\forest at execandmemoize@true
+ \csname forest at memo@orig@\string#1\endcsname{##1}%
+ \global\forest at execandmemoize@false
+ \global\forest at memoizing@now at false
+ \ifforest at memoizing@ok@
+ \csxdef{\the\forest at memo@key}{\the\forest at memo}%
+ \immediate\write\forest at memo@out{%
+ \noexpand\forest at memo@load{\the\forest at memo@key}{\the\forest at memo}%
+ }%
+ \fi
+ }%
+ \fi
+ \fi
+ }%
+}
+\def\forest at memo@load#1#2{%
+ \def\forest at temp@key{#1}%
+ \def\forest at temp@value{#2}%
+ \csxdef{\detokenize\expandafter{\forest at temp@key}}{\expandonce\forest at temp@value}%
+ \immediate\write\forest at memo@out{%
+ \noexpand\forest at memo@load{\detokenize\expandafter{\forest at temp@key}}{\detokenize\expandafter{\forest at temp@value}}%
+ }%
+}
+\forestset{
+ TeX and memoize/.code={\forest at execandmemoize{#1}},
+}
+\def\forest at execandmemoize#1{%
+ \ifforest at execandmemoize@
+ \let\forest at memo@next\forest at execandmemoize@
+ \else
+ \let\forest at memo@next\@gobble
+ \fi
+ \forest at memo@next{#1}%
+ #1%
+}
+\def\forest at execandmemoize@#1{%
+ \gapptotoks\forest at memo{#1}%
+}
+\def\forest at memo@filename{\jobname.memo}
+\newwrite\forest at memo@out
+\immediate\openout\forest at memo@out=\forest at memo@filename.tmp
+\IfFileExists{\forest at memo@filename}{%
+ \input\forest at memo@filename\relax
+}{}%
+\AtEndDocument{%
+ \immediate\closeout\forest at memo@out
+ \forest at file@copy{\forest at memo@filename.tmp}{\forest at memo@filename}%
+}
+\forest at memoize\forestindex at index@
\index(not print,not index)[%
set={
index key=unknown,
Modified: trunk/Master/texmf-dist/tex/latex/forest/forest-lib-edges.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/forest/forest-lib-edges.sty 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/tex/latex/forest/forest-lib-edges.sty 2016-12-06 00:28:11 UTC (rev 42640)
@@ -8,7 +8,7 @@
%%
%% `forest-libs' is a collection of libraries for package `forest'.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -29,23 +29,26 @@
%% `forest.dtx', or the derived `forest.sty'.
%%
\RequirePackage{forest}
-\ProvidesForestLibrary{edges}[2015/11/14 v0.1]
+\ProvidesForestLibrary{edges}[2016/12/05 v0.1.1]
\forestset{
declare dimen={fork sep}{0.5em},
- forked edge/.style={
- edge={rotate/.pgfmath=grow()},
+ forked edge'/.style={
+ edge={rotate/.option=!parent.grow},
edge path'={(!u.parent anchor) -- ++(\forestoption{fork sep},0) |- (.child anchor)},
},
- forked edges/.style={
- for tree={parent anchor=children},
- for descendants={child anchor=parent,forked edge}
+ forked edge/.style={
+ on invalid={fake}{!parent.parent anchor=children},
+ child anchor=parent,
+ forked edge',
},
+ forked edges/.style={for nodewalk={#1}{forked edge}},
+ forked edges/.default=tree,
}
\forestset{
declare dimen register=folder indent,
folder indent=.45em,
folder/.style={
- parent anchor=parent last,
+ parent anchor=-children last,
anchor=parent first,
calign=child,
calign primary child=1,
@@ -52,7 +55,7 @@
for children={
child anchor=parent,
anchor=parent first,
- edge={rotate/.pgfmath=grow()},
+ edge={rotate/.option=!parent.grow},
edge path'/.expanded={
([xshift=\forestregister{folder indent}]!u.parent anchor) |- (.child anchor)
},
Modified: trunk/Master/texmf-dist/tex/latex/forest/forest-lib-linguistics.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/forest/forest-lib-linguistics.sty 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/tex/latex/forest/forest-lib-linguistics.sty 2016-12-06 00:28:11 UTC (rev 42640)
@@ -8,7 +8,7 @@
%%
%% `forest-libs' is a collection of libraries for package `forest'.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
Modified: trunk/Master/texmf-dist/tex/latex/forest/forest.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/forest/forest.sty 2016-12-05 23:41:06 UTC (rev 42639)
+++ trunk/Master/texmf-dist/tex/latex/forest/forest.sty 2016-12-06 00:28:11 UTC (rev 42640)
@@ -8,7 +8,7 @@
%%
%% `forest' is a `pgf/tikz'-based package for drawing (linguistic) trees.
%%
-%% Copyright (c) 2015 Saso Zivanovic
+%% Copyright (c) 2016 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic at guest.arnes.si
%%
@@ -44,7 +44,7 @@
%% - LICENCE
%% To use the package, only the files marked with + need to be installed.
%%
-\ProvidesPackage{forest}[2016/04/09 v2.0.3 Drawing (linguistic) trees]
+\ProvidesPackage{forest}[2016/12/05 v2.1 Drawing (linguistic) trees]
\RequirePackage{tikz}[2013/12/13]
\usetikzlibrary{shapes}
@@ -58,7 +58,74 @@
\RequirePackage{environ}
\RequirePackage{xparse}
-
+\RequirePackage{inlinedef}
+\newtoks\ID at usercommands{}
+\newcommand\NewInlineCommand[3][0]{%
+ \newcommand#2[#1]{#3}%
+ \ID at usercommands\xa{%
+ \the\ID at usercommands
+ \ifx\@foo#2%
+ \def\next{\ID at expandunsafe#2}%
+ \fi
+ }%
+}
+\def\@ExpandIfTF#1{%
+ \csname
+ % I'm not 100% sure if this plays well in every situation
+ \csname if#1\endcsname
+ @firstoftwo%
+ \else
+ @secondoftwo%
+ \fi
+ \endcsname
+}
+\patchcmd{\ID at switch}
+ {\ifcat\noexpand\@foo\space}
+ {\the\ID at usercommands\ifcat\noexpand\@foo\space}
+ {%
+ \NewInlineCommand[2]\ExpandIfT{%
+ \MultiExpand{3}{%
+ \@ExpandIfTF{#1}{#2}{}%
+ }%
+ }
+ \NewInlineCommand[2]\ExpandIfF{%
+ \MultiExpand{3}{%
+ \@ExpandIfTF{#1}{}{#2}%
+ }%
+ }
+ \NewInlineCommand[3]\ExpandIfTF{%
+ \MultiExpand{3}{%
+ \@ExpandIfTF{#1}{#2}{#3}%
+ }%
+ }%
+ \newcommand\InlineNoDef[1]{%
+ \begingroup
+ % Define a few ``quarks''
+ \def\Expand{\Expand}\def\Super{\Super}%
+ \def\UnsafeExpand{\UnsafeExpand}\def\MultiExpand{\MultiExpand}%
+ \def\Recurse{\Recurse}\def\NoExpand{\NoExpand}%
+ \def\Q at END{\Q at END}%
+ % Define a toks register
+ \ID at toks{}%
+ % Signal that we need to look for a star
+ \@testtrue\ID at starfalse\ID at starstarfalse\ID at bangfalse
+ % Start scanning for \def or \gdef
+ \ID at scan#1\Q at END{}%
+ \expandafter\endgroup
+ %\expandafter\@firstofone
+ \the\ID at toks
+ }%
+ }%
+ {%
+ \PackageWarning{forest}{Could not patch inlinedef! Disabling it. Except in some special situations (nested arrays), stuff will probably still work, but there's no guarantee. Please report this situation to the author (but check first if a new version already exists).}{}%
+ \let\Inline\relax
+ \def\Expand#1{#1}%
+ \def\MultiExpand#1#2{#2}%
+ \def\InlineNoDef#1{#1}%
+ \def\ExpandIfT#1#2{\@ExpandIfTF{#1}{#2}{}}%
+ \def\ExpandIfF#1#2{\@ExpandIfTF{#1}{}{#2}}%
+ \def\ExpandIfTF#1#2#3{\@ExpandIfTF{#1}{#2}{#3}}%
+ }
\pgfkeys{/forest/.is family}
\def\forestset#1{\pgfqkeys{/forest}{#1}}
\newif\ifforest at external@
@@ -66,12 +133,15 @@
\newif\ifforest at install@keys at to@tikz at path@
\newif\ifforestdebugnodewalks
\newif\ifforestdebugdynamics
+\newif\ifforestdebugprocess
+\newif\ifforestdebugtemp
+\newif\ifforestdebug
\def\forest at compat{}
\forestset{package at options/.cd,
external/.is if=forest at external@,
tikzcshack/.is if=foresttikzcshack,
tikzinstallkeys/.is if=forest at install@keys at to@tikz at path@,
- compat/.store in=\forest at compat,
+ compat/.code={\appto\forest at compat{,#1}},
compat/.default=most,
.unknown/.code={% load library
\eappto\forest at loadlibrarieslater{%
@@ -79,10 +149,11 @@
\noexpand\forestapplylibrarydefaults{\pgfkeyscurrentname}%
}%
},
- debug/.code={\pgfqkeys{/forest/package at options/debug}{#1}},
- debug/.default={nodewalks,dynamics},
+ debug/.code={\forestdebugtrue\pgfqkeys{/forest/package at options/debug}{#1}},
+ debug/.default={nodewalks,dynamics,process},
debug/nodewalks/.is if=forestdebugnodewalks,
debug/dynamics/.is if=forestdebugdynamics,
+ debug/process/.is if=forestdebugprocess,
}
\forest at install@keys at to@tikz at path@true
\foresttikzcshacktrue
@@ -93,10 +164,17 @@
\forcsvlist\useforestlibrary@@{#3}%
\IfBooleanT{#1}{\forestapplylibrarydefaults{#3}}%
}
-\def\useforestlibrary@#1#2{\RequirePackage[#1]{forest-lib-#2}}
+\def\useforestlibrary@#1#2{%
+ \RequirePackage[#1]{forest-lib-#2}%
+ \csuse{forest at compat@libraries@#2}%
+}
\def\forestapplylibrarydefaults#1{\forcsvlist\forestapplylibrarydefaults@{#1}}
\def\forestapplylibrarydefaults@#1{\forestset{libraries/#1/defaults/.try}}
-\NewDocumentCommand\ProvidesForestLibrary{m O{}}{\ProvidesPackage{forest-lib-#1}[#2]}
+\NewDocumentCommand\ProvidesForestLibrary{m O{}}{%
+ \ProvidesPackage{forest-lib-#1}[#2]%
+ \csdef{forest at libraries@loaded@#1}{}%
+}
+\def\forest at iflibraryloaded#1#2#3{\ifcsdef{forest at libraries@loaded@#1}{#2}{#3}}
\ProcessPgfPackageOptions{/forest/package at options}
\def\forest at patch#1#2#3#4#5{%
% #1 = cs to be patched
@@ -120,9 +198,25 @@
}{%
\edef#1{{\pgf at pt@aa}{\pgf at pt@ab}{\pgf at pt@ba}{\pgf at pt@bb}{\the\pgf at pt@x}{\the\pgf at pt@y}}%
}
+\def\forest at empty{}
\long\def\@escapeif#1#2\fi{\fi#1}
\long\def\@escapeifif#1#2\fi#3\fi{\fi\fi#1}
\long\def\@escapeififif#1#2\fi#3\fi#4\fi{\fi\fi\fi#1}
+\def\forest at repeat@n at times#1{% #1=n, #2=code
+ \expandafter\forest at repeat@n at times@\expandafter{\the\numexpr#1}}
+\def\forest at repeat@n at times@#1{%
+ \ifnum#1>0
+ \@escapeif{%
+ \expandafter\forest at repeat@n at times@@\expandafter{\the\numexpr#1-1}%
+ }%
+ \else
+ \expandafter\@gobble
+ \fi
+}
+\def\forest at repeat@n at times@@#1#2{%
+ #2%
+ \forest at repeat@n at times@{#1}{#2}%
+}
\def\newloop#1{%
\count@=\escapechar
\escapechar=-1
@@ -398,6 +492,7 @@
\def\forest at temp@macro####1{#4}%
\csname forest at temp#5\endcsname
\edef\forest at temp@value{\ifforest at temp\expandafter\forestOv\expandafter{\expandafter\forest at setter@node\expandafter}\else\expandafter\forestrv\fi{#2}}%
+ %\expandafter\expandafter\expandafter\pgfkeysalso\expandafter\expandafter\expandafter{\expandafter\forest at temp@macro\expandafter{\forest at temp@value}}% ??? how many expansions are really needed?
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\pgfkeysalso\expandafter\expandafter\expandafter{\expandafter\forest at temp@macro\expandafter{\forest at temp@value}}%
}%
}{}%
@@ -449,6 +544,690 @@
\fi
}%
}
+\forestset{
+ show register/.code={%
+ \forestrget{#1}\foresttemp
+ \typeout{Forest register "#1"=\expandafter\detokenize\expandafter{\foresttemp}}%
+ },
+}
+\def\forest at newarray#1{%
+ \forest at tempfalse % non-global
+ {%
+ \escapechar=-1
+ \expandafter\escapechar\expandafter\count@\expandafter
+ }%
+ \expandafter\forest at newarray@\expandafter{\string#1}%
+}
+\def\forest at newglobalarray#1{%
+ \forest at temptrue % global
+ {%
+ \escapechar=-1
+ \expandafter\escapechar\expandafter\count@\expandafter
+ }%
+ \expandafter\forest at newarray@\expandafter{\string#1}%
+}
+\def\forest at array@empty at error#1{%
+ \PackageError{forest}{Cannot pop from empty array "#1".}{}}%
+\def\forest at array@oub at error#1#2{%
+ \PackageError{forest}{#2 is out of bounds of array "#1"
+ (\the\csuse{#1M}--\the\csuse{#1N}).}{}}%
+\def\forest at newarray@#1{%
+ % array bounds: M <= i < N
+ \expandafter\newcount\csname#1M\endcsname
+ \expandafter\newcount\csname#1N\endcsname
+ \csedef{#1clear}{%
+ \ifforest at temp\global\fi\expandonce{\csname#1M\endcsname}0
+ \ifforest at temp\global\fi\expandonce{\csname#1N\endcsname}0
+ }%
+ \csedef{#1ifempty}{%
+ \noexpand\ifnum\expandonce{\csname#1M\endcsname}<\expandonce{\csname#1N\endcsname}\relax
+ \unexpanded{\expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi}%
+ }%
+ \csedef{#1length}{% a numexpr
+ \noexpand\numexpr\expandonce{\csname#1N\endcsname}-\expandonce{\csname#1M\endcsname}\relax
+ }%
+ \csedef{#1checkrange}##1##2{% args can be \numexprs
+ \noexpand\forest at tempfalse
+ \noexpand\ifnum\numexpr##1<\expandonce{\csname#1M\endcsname}\relax
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifnum\numexpr##2>\expandonce{\csname#1N\endcsname}\relax
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifforest at temp
+ \noexpand\forest at array@oub at error{#1}{Range "\noexpand\number\noexpand\numexpr##1\relax--\noexpand\number\noexpand\numexpr##2\relax"}%
+ \noexpand\fi
+ }%
+ \csedef{#1checkindex}##1{% arg can be a \numexpr
+ \noexpand\forest at tempfalse
+ \noexpand\ifnum\numexpr##1<\expandonce{\csname#1M\endcsname}\relax
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifnum\numexpr##1<\expandonce{\csname#1N\endcsname}\relax
+ \noexpand\else
+ \noexpand\forest at temptrue
+ \noexpand\fi
+ \noexpand\ifforest at temp
+ \noexpand\forest at array@oub at error{#1}{Index "\noexpand\number\noexpand\numexpr##1\relax"}%
+ \noexpand\fi
+ }%
+ \csedef{#1get}##1##2{% ##1 = index, ##2 = receiving cs
+ \expandonce{\csname#1checkindex\endcsname}{##1}%
+ \noexpand\letcs##2{#1##1}%
+ }%
+ \csedef{#1get@}##1##2{% ##1 = index, ##2 = receiving cs (don't check bounds)
+ \noexpand\letcs##2{#1##1}%
+ }%
+ \csedef{#1toppop}##1{% ##1 = receiving cs
+ \expandonce{\csname#1ifempty\endcsname}{%
+ \noexpand\forest at array@empty at error{#1}%
+ }{%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}-1
+ \noexpand\letcs\noexpand##1{#1\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ }%
+ }%
+ \InlineNoDef{\csdef{#1bottompop}##1{% ##1 = receiving cs
+ \Expand{\csname#1ifempty\endcsname}{%
+ \forest at array@empty at error{#1}%
+ }{%
+ \letcs##1{#1\the\Expand{\csname#1M\endcsname}}%
+ \ExpandIfT{forest at temp}\global\advance\Expand{\csname#1M\endcsname 1}%
+ }%
+ }}%
+ % \csdef{#1bottompop}##1{}% we need this as \Inline chokes on \let\macro=\relax
+ % \expandafter\Inline\expandafter\def\csname#1bottompop\endcsname##1{% ##1 = receiving cs
+ % \Expand{\csname#1ifempty\endcsname}{%
+ % \forest at array@empty at error{#1}%
+ % }{%
+ % \letcs##1{#1\the\Expand{\csname#1M\endcsname}}%
+ % \ExpandIfT{forest at temp}\global\advance\Expand{\csname#1M\endcsname 1}%
+ % }%
+ % }%
+ % \csedef{#1bottompop}##1{% ##1 = receiving cs
+ % \expandonce{\csname#1ifempty\endcsname}{%
+ % \noexpand\forest at array@empty at error{#1}%
+ % }{%
+ % \noexpand\letcs\noexpand##1{#1\noexpand\the\expandonce{\csname#1M\endcsname}}%
+ % \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}1
+ % }%
+ % }%
+ \csedef{#1setappend}##1{% ##1 = definition
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi
+ {#1\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ {\noexpand\unexpanded{##1}}%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ }%
+ \csedef{#1setappend@}##1##2{% ##1 = continue by, ##2 = definition
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi
+ {#1\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ {\noexpand\unexpanded{##2}}%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ ##1%
+ }%
+ \csedef{#1setprepend}##1{% ##1 = definition
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}-1
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi
+ {#1\noexpand\the\expandonce{\csname#1M\endcsname}}%
+ {\noexpand\unexpanded{##1}}%
+ }%
+ \csedef{#1esetappend}##1{% ##1 = definition
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi{#1\noexpand\the\expandonce{\csname#1N\endcsname}}{##1}%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ }%
+ \csedef{#1esetprepend}##1{% ##1 = definition
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}-1
+ \ifforest at temp\noexpand\csxdef\else\noexpand\csedef\fi{#1\noexpand\the\expandonce{\csname#1M\endcsname}}{##1}%
+ }%
+ \csedef{#1letappend}##1{% ##1 = cs
+ \ifforest at temp\noexpand\expandafter\noexpand\global\fi\noexpand\expandafter\noexpand\let
+ \noexpand\csname#1\noexpand\the\expandonce{\csname#1N\endcsname}\noexpand\endcsname
+ ##1%
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1N\endcsname}1
+ }%
+ \csedef{#1letprepend}##1{% ##1 = cs
+ \ifforest at temp\global\fi\advance\expandonce{\csname#1M\endcsname}-1
+ \ifforest at temp\noexpand\expandafter\noexpand\global\fi\noexpand\expandafter\noexpand\let
+ \noexpand\csname#1\noexpand\the\expandonce{\csname#1M\endcsname}\noexpand\endcsname
+ ##1%
+ }%
+ \csedef{#1values}{%
+ \noexpand\expandafter\noexpand\expandafter\noexpand\expandafter\expandonce{\csname#1valuesfromrange\endcsname}%
+ \noexpand\expandafter\noexpand\expandafter\noexpand\expandafter{%
+ \noexpand\expandafter\noexpand\the
+ \noexpand\expandafter\expandonce{\csname#1M\endcsname}%
+ \noexpand\expandafter}%
+ \noexpand\expandafter{\noexpand\the\expandonce{\csname#1N\endcsname}}%
+ }%
+ \csedef{#1valuesfromrange}##1##2{% ##1/##2 = lower/upper bounds (we receive them expanded)
+ \noexpand\ifnum##1<##2
+ {\noexpand\expandafter\noexpand\expandonce\noexpand\expandafter{\noexpand\csname#1##1\noexpand\endcsname}}% here we add braces (for the general case, we might want an arbitrary prefix&suffix)
+ \noexpand\expandafter\noexpand\@escapeif\noexpand\expandafter{\noexpand\expandafter\expandonce{\csname#1valuesfromrange\endcsname}%
+ \noexpand\expandafter{\noexpand\number\noexpand\numexpr##1+1}{##2}}%
+ \noexpand\fi
+ }%
+ \csdef{#1topextend}{\def\forest at array@currentarray{#1}\forest at array@topextend}%
+}
+\def\forest at array@topextend{\futurelet\forest at ate@next at token\forest at ate@checkforspace}
+\def\forest at ate@checkforspace{%
+ \expandafter\ifx\space\forest at ate@next at token
+ \expandafter\forest at ate@havespace
+ \else
+ \expandafter\forest at ate@checkforgroup
+ \fi
+}
+\def\forest at ate@havespace{\expandafter\forest at array@topextend\romannumeral-`0}%
+\def\forest at ate@checkforgroup{%
+ \ifx\forest at ate@next at token\bgroup
+ \expandafter\forest at ate@appendgroup
+ \else
+ \expandafter\forest at ate@checkforeov
+ \fi
+}
+\def\forest at ate@appendgroup{%
+ \expandonce{\csname\forest at array@currentarray setappend@\endcsname}\forest at array@topextend
+}
+\def\forest at ate@checkforeov{%
+ \ifx\forest at ate@next at token\forest at eov
+ \expandafter\forest at ate@finish
+ \else
+ \expandafter\forest at ate@appendtoken
+ \fi
+}
+\def\forest at ate@appendtoken#1{%
+ \expandonce{\csname\forest at array@currentarray setappend\endcsname}{#1}%
+ \forest at array@topextend
+}
+\def\forest at ate@finish\forest at eov{\forest at topextend@next}
+\let\forest at topextend@next\relax
+\forest at newarray\forest at temparray@
+\forest at newglobalarray\forest at global@temparray@
+\def\forest at eon{ }
+\newif\ifforest at isnum@minus
+\newif\ifforest at isnum
+\def\forest at isnum#1{%
+ \forest at isnum@minusfalse
+ \let\forest at isnum@next\forest at isnum@finish
+ \edef\forest at isnum@temp{#1}%
+ \expandafter\forest at isnum@a\forest at isnum@temp\forest at eon\forest at eon\forest at END
+ \ifforest at isnum
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\def\forest at isnum@a{\futurelet\forest at isnum@token\forest at isnum@b}
+\def\forest at isnum@minustoggle{%
+ \ifforest at isnum@minus\forest at isnum@minusfalse\else\forest at isnum@minustrue\fi
+}
+\def\forest at isnum@b{%
+ \let\forest at next\forest at isnum@p
+ \ifx-\forest at isnum@token
+ \forest at isnum@minustoggle
+ \let\forest at next\forest at isnum@c
+ \else
+ \ifx+\forest at isnum@token
+ \let\forest at next\forest at isnum@c
+ \else
+ \expandafter\ifx\space\forest at isnum@token
+ \let\forest at next\forest at isnum@s
+ \fi
+ \fi
+ \fi
+ \forest at next
+}
+\def\forest at isnum@c#1{\forest at isnum@a}%
+\def\forest at isnum@s#1{\forest at isnum@a#1}%
+\newcount\forest at isnum@count
+\def\forest at isnum@p{%
+ \ifx0\forest at isnum@token
+ \let\forest at next\forest at isnum@next
+ \else
+ \let\forest at next\forest at isnum@nz@
+ \fi
+ \forest at isnumtrue
+ \afterassignment\forest at isnum@q\forest at isnum@count\ifforest at isnum@minus-\fi0%
+}
+\def\forest at isnum@q{%
+ \futurelet\forest at isnum@token\forest at next
+}
+\def\forest at isnum@nz@{%
+ \ifnum\forest at isnum@count=0
+ \forest at isnumfalse
+ \fi
+ \forest at isnum@next
+}
+\def\forest at isnum@finish#1\forest at END{%
+ \ifx\forest at isnum@token\forest at eon
+ \else
+ \forest at isnumfalse
+ \fi
+}
+\newcount\forest at isdim@nonintpart
+\newif\ifforest at isdim
+\def\forest at isdim#1{%
+ \forest at isdimfalse
+ \forest at isnum@minusfalse
+ \def\forest at isdim@leadingzeros{}%
+ \forest at isdim@nonintpart=0
+ \def\forest at isdim@unit{pt}%
+ \let\forest at isnum@next\forest at isdim@checkfordot
+ \edef\forest at isnum@temp{#1}%
+ \expandafter\forest at isnum@a\forest at isnum@temp\forest at eon\forest at eon\forest at eon\forest at eon\forest at END
+ \ifforest at isdim
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\def\forest at isdim@checkfordot{%
+ \ifx.\forest at isnum@token
+ \expandafter\forest at isdim@dot
+ \else
+ \ifx,\forest at isnum@token
+ \expandafter\expandafter\expandafter\forest at isdim@dot
+ \else
+ \expandafter\expandafter\expandafter\forest at isdim@nodot
+ \fi
+ \fi
+}
+\def\forest at isdim@nodot{%
+ \ifforest at isnum
+ \expandafter\forest at isdim@checkforunit
+ \else
+ \expandafter\forest at isdim@finish at nodim
+ \fi
+}
+\def\forest at isdim@dot#1{% #1=. or ,
+ \futurelet\forest at isnum@token\forest at isdim@collectzero
+}
+\def\forest at isdim@collectzero{%
+ \ifx0\forest at isnum@token
+ \expandafter\forest at isdim@collectzero@
+ \else
+ \expandafter\forest at isdim@getnonintpart
+ \fi
+}
+\def\forest at isdim@collectzero@#1{% #1 = 0
+ \appto\forest at isdim@leadingzeros{0}%
+ \futurelet\forest at isnum@token\forest at isdim@collectzero
+}
+\def\forest at isdim@getnonintpart{%
+ \afterassignment\forest at isdim@checkforunit\forest at isdim@nonintpart0%
+}
+\def\forest at def@unit#1{\csdef{forest at unit@#1}{#1}}
+\forest at def@unit{em}
+\forest at def@unit{ex}
+\forest at def@unit{pt}
+\forest at def@unit{pc}
+\forest at def@unit{in}
+\forest at def@unit{bp}
+\forest at def@unit{cm}
+\forest at def@unit{mm}
+\forest at def@unit{dd}
+\forest at def@unit{cc}
+\forest at def@unit{sp}
+\def\forest at isdim@checkforunit#1#2{%
+ \lowercase{\edef\forest at isnum@temp{\detokenize{#1#2}}}%
+ \ifcsname forest at unit@\forest at isnum@temp\endcsname
+ \let\forest at isdim@next\forest at isdim@finish at dim
+ \edef\forest at isdim@unit{\csname forest at unit@\forest at isnum@temp\endcsname}%
+ \else
+ \ifx#1\forest at eon
+ \let\forest at isdim@next\forest at isdim@finish at dim
+ \else
+ \let\forest at isdim@next\forest at isdim@finish at nodim
+ \fi
+ \fi
+ \forest at isdim@next
+}
+\def\forest at isdim@finish at dim{%
+ \futurelet\forest at isnum@token\forest at isdim@finish at dim@a
+}
+\def\forest at isdim@finish at dim@a{%
+ \expandafter\ifx\space\forest at isnum@token
+ \expandafter\forest at isdim@finish at dim@b
+ \else
+ \expandafter\forest at isdim@finish at dim@c
+ \fi
+}
+\expandafter\def\expandafter\forest at isdim@finish at dim@b\space{% eat one space
+ \futurelet\forest at isnum@token\forest at isdim@finish at dim@c
+}
+\def\forest at isdim@finish at dim@c#1\forest at END{%
+ \ifx\forest at isnum@token\forest at eon
+ \forest at isdimtrue
+ \forest at isdim@dimen\the\forest at isnum@count.\forest at isdim@leadingzeros\the\forest at isdim@nonintpart\forest at isdim@unit\relax
+ \else
+ \forest at isdimfalse
+ \fi
+}
+\def\forest at isdim@finish at nodim#1\forest at END{%
+ \forest at isdimfalse
+}
+\newdimen\forest at isdim@dimen
+ % \long\def\@firstofthree#1#2#3{#3} % defined by LaTeX
+\long\def\@firstofthree#1#2#3{#1}
+\long\def\@secondofthree#1#2#3{#2}
+\def\forest at isnumdim#1{%
+ \forest at isdim{#1}{%
+ \forest at isnumdim@
+ }{%
+ \@thirdofthree
+ }%
+}
+\def\forest at isnumdim@{%
+ \ifforest at isnum
+ \expandafter\@firstofthree
+ \else
+ \expandafter\@secondofthree
+ \fi
+}
+\def\forestmathtype at generic{_} % generic (token list)
+\def\forestmathtype at count{n} % integer
+\def\forestmathtype at dimen{d} % a dimension: <decimal> pt
+\def\forestmathtype at unitless{P} % <decimal> (a unitless dimension) (P because pgfmath returns such numbers)
+\def\forestmathtype at textasc{t} % text (ascending)
+\def\forestmathtype at textdesc{T} % text (descending)
+\def\forestmathtype at array{a} % array - internal
+\def\forestmathtype at none{} % internal (for requests - means whatever)
+\def\forestmathresult{}
+\let\forestmathresulttype\forestmathtype at generic
+\def\forest at tryprocess{%
+ \expandafter\forest at tryprocess@a\romannumeral-`0}
+\def\forest at tryprocess@a{\futurelet\forest at temp@token\forest at tryprocess@b}
+\def\forest at tryprocess@b{%
+ \ifx>\forest at temp@token
+ \expandafter\forest at tryprocess@yes
+ \else
+ \expandafter\forest at tryprocess@no
+ \fi
+}
+\def\forest at spacegen{ \forest at spacegen}
+\def\forest at tryprocess@yes#1#2\forest at spacegen{%
+ \forest at process{false}#2\forest at eov
+ \@firstoftwo
+}
+\def\forest at tryprocess@no#1\forest at spacegen{\@secondoftwo}
+\def\forestmathsetcount#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ #1=\forest at process@result\relax
+ }{%
+ \forestmathsetcount@#1{#2}%
+ }%
+}
+\def\forestmathsetcount@#1#2{%
+ \forest at isnum{#2}{%
+ #1=\forest at isnum@count
+ }{%
+ \pgfmathsetcount#1{#2}%
+ }%
+}
+\def\forestmathsetlength#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ #1=\forest at process@result\relax
+ }{%
+ \forestmathsetlength@#1{#2}%
+ }%
+}
+\def\forestmathsetlength@#1#2{%
+ \forest at isdim{#2}{%
+ #1=\forest at isdim@dimen
+ }{%
+ \pgfmathsetlength#1{#2}%
+ }%
+}
+\def\forestmathtruncatemacro#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ \forest at temp@count=\forest at process@result\relax
+ \edef#1{\the\forest at temp@count}%
+ }{%
+ \forestmathtruncatemacro@#1{#2}%
+ }%
+}
+\def\forestmathtruncatemacro@#1#2{%
+ \forest at isnum{#2}{%
+ \edef#1{\the\forest at isnum@count}%
+ }{%
+ \pgfmathtruncatemacro#1{#2}%
+ }%
+}
+\def\forestmathsetlengthmacro#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ \forest at temp@dimen=\forest at process@result\relax
+ \edef#1{\the\forest at temp@dimen}%
+ }{%
+ \forestmathsetlengthmacro@#1{#2}%
+ }%
+}
+\def\forestmathsetlengthmacro@#1#2{%
+ \forest at isdim{#2}{%
+ \edef#1{\the\forest at isdim@dimen}%
+ }{%
+ \pgfmathsetlengthmacro#1{#2}%
+ }%
+}
+\def\forestmathsetmacro#1#2{%
+ \forest at tryprocess#2\forest at spacegen{%
+ \let#1\forest at process@result
+ \let\forestmathresulttype\forest at process@result at type
+ }{%
+ \forestmathsetmacro@#1{#2}%
+ \def\forestmathresulttype{P}%
+ }%
+}
+\def\forestmathsetmacro@#1#2{%
+ \forest at isdim{#2}{%
+ \edef#1{\expandafter\Pgf at geT\the\forest at isdim@dimen}%
+ }{%
+ \pgfmathsetmacro#1{#2}%
+ }%
+}
+\def\forestmathparse#1{%
+ \forest at tryprocess#1\forest at spacegen{%
+ \let\forestmathresult\forest at process@result
+ \let\forestmathresulttype\forest at process@result at type
+ }{%
+ \forestmathparse@{#1}%
+ \def\forestmathresulttype{P}%
+ }%
+}
+\def\forestmathparse@#1{%
+ \forest at isdim{#1}{%
+ \edef\forestmathresult{\expandafter\Pgf at geT\the\forest at isdim@dimen}%
+ }{%
+ \pgfmathsetmacro\forestmathresult{#1}%
+ }%
+}
+\csdef{forest at bh@0}{0}
+\csdef{forest at bh@false}{0}
+\csdef{forest at bh@1}{1}
+\csdef{forest at bh@true}{1}
+\def\forestmath at if#1{%
+ \ifcsdef{forest at bh@\detokenize{#1}}{%
+ \let\forest at next\forestmath at if@fast
+ }{%
+ \let\forest at next\forestmath at if@slow
+ }%
+ \forest at next{#1}%
+ \ifnum\forest at temp=0
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+}
+\def\forestmath at if@fast#1{\letcs\forest at temp{forest at bh@\detokenize{#1}}}
+\def\forestmath at if@slow#1{\forestmathtruncatemacro\forest at temp{#1}}
+\def\forestmath at convert@fromto#1#2#3{%
+ \edef\forestmathresult{\csname forestmath at convert@from@#1 at to@#2\endcsname{#3}}}
+\def\forestmath at convert@from#1{\forestmath at convert@fromto{#1}{\forestmathresulttype}}
+\def\forestmath at convert@to{\forestmath at convert@fromto{\forestmathresulttype}}
+\def\forestmath at convert@from at n@to at n#1{#1}
+\def\forestmath at convert@from at n@to at d#1{#1\pgfmath at pt}
+\def\forestmath at convert@from at n@to at P#1{#1}
+\def\forestmath at convert@from at d@to at n#1{%
+ \expandafter\forestmath at convert@uptodot\Pgf at geT#1.\forest at eov}
+\def\forestmath at convert@from at d@to at d#1{#1}
+\def\forestmath at convert@from at d@to at P#1{\Pgf at geT#1}
+\def\forestmath at convert@from at P@to at n#1{%
+ \forestmath at convert@uptodot#1.\forest at eov}
+\def\forestmath at convert@from at P@to at d#1{#1\pgfmath at pt}
+\def\forestmath at convert@from at P@to at P#1{#1}
+\def\forestmath at convert@uptodot#1.#2\forest at eov{#1}
+\def\forestmathzero{\forestmath at convert@from\forestmathtype at count{0}}
+\csdef{forestmath at convert@from at n@to at _}#1{\unexpanded{#1}}
+\csdef{forestmath at convert@from at d@to at _}#1{\unexpanded{#1}}
+\csdef{forestmath at convert@from at P@to at _}#1{\unexpanded{#1}}
+\def\forestmathsettypefrom#1{%
+ \forest at isnumdim{%
+ \let\forestmathresulttype\forest at result@type at numexpr
+ }{%
+ \let\forestmathresulttype\forest at result@type at dimexpr
+ }{%
+ \let\forestmathresulttype\forest at result@type at pgfmath
+ }%
+}
+\def\forestmathadd#1#2{\edef\forestmathresult{%
+ \csname forestmathadd@\forestmathresulttype\endcsname{#1}{#2}}}
+\def\forestmathadd@#1#2#3{\edef\forestmathresult{%
+ \csname forestmathadd@#1\endcsname{#2}{#3}}}
+\def\forestmathadd at n#1#2{\the\numexpr#1+#2\relax}
+\def\forestmathadd at d#1#2{\the\dimexpr#1+#2\relax}
+\def\forestmathadd at P#1#2{\expandafter\Pgf at geT\the\dimexpr#1pt+#2pt\relax}
+\def\forestmathmultiply#1#2{%
+ \csname forestmathmultiply@\forestmathresulttype\endcsname{#1}{#2}}
+\def\forestmathmultiply@#1#2#3{%
+ \csname forestmathmultiply@#1\endcsname{#2}{#3}}
+\def\forestmathmultiply at n#1#2{\edef\forestmathresult{%
+ \the\numexpr#1*#2\relax}}
+\def\forestmathmultiply at d#1#2{%
+ \edef\forestmath at marshal{\forestmathmultiply at d@{#1}{#2}}\forestmath at marshal
+}
+\def\forestmathmultiply at d@#1#2{%
+ \edef\forestmath at marshal{%
+ \noexpand\pgfmathmultiply@{\Pgf at geT#1}{\Pgf at geT#2}%
+ }\forestmath at marshal
+ \edef\forestmathresult{\pgfmathresult\pgfmath at pt}%
+}
+\def\forestmathmultiply at P#1#2{%
+ \pgfmathmultiply@{#1}{#2}%
+ \let\forestmathresult\pgfmathresult
+}
+\def\forestmathdivide#1#2{%
+ \csname forestmathdivide@\forestmathresulttype\endcsname{#1}{#2}}
+\def\forestmathdivide@#1#2#3{%
+ \csname forestmathdivide@#1\endcsname{#2}{#3}}
+\def\forestmathdivide at n#1#2{\edef\forestmathresult{%
+ \the\numexpr#1/#2\relax}}
+\def\forestmathdivide at d#1#2{\edef\forestmathresult{%
+ \the\dimexpr#1/#2\relax}}
+\def\forestmathdivide at P#1#2{%
+ \edef\forest at marshal{%
+ \noexpand\pgfmathdivide{+#1}{+#2}%
+ }\forest at marshal
+ \let\forestmathresult\pgfmathresult
+}
+\def\forestmathtrue{%
+ \def\forestmathresult{1}%
+ \let\forestmathresulttype\forestmathtype at count}
+\def\forestmathfalse{%
+ \def\forestmathresult{0}%
+ \let\forestmathresulttype\forestmathtype at count}
+\def\forestmath at if@lt at n#1#2{\ifnum#1<#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at d#1#2{\ifdim#1<#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at P#1#2{\ifdim#1pt<#2pt
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at t#1#2{\ifnum\pdfstrcmp{#1}{#2}<0
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@lt at T#1#2{\ifnum\pdfstrcmp{#1}{#2}>0
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forest at cmp@error#1#2{\PackageError{forest}{Comparison
+ ("<" or ">") of generic type arguments "#1" and "#2"
+ makes no sense}{Use one of argument processor instructions
+ "n", "d", "P" or "t" to change the type. Use package option
+ "debug=process" to see what's happening here.}}
+\cslet{forestmath at if@lt at _}\forest at cmp@error
+\def\forestmath at if@eq at n#1#2{\ifnum#1=#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@eq at d#1#2{\ifdim#1=#2\relax
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@eq at P#1#2{\ifdim#1pt=#2pt
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmath at if@eq at t#1#2{\ifnum\pdfstrcmp{#1}{#2}=0
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\let\forestmath at if@eq at T\forestmath at if@eq at t
+\csdef{forestmath at if@eq at _}#1#2{%
+ \def\forestmath at tempa{#1}%
+ \def\forestmath at tempb{#2}%
+ \ifx\forestmath at tempa\forestmath at tempb
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\def\forestmathlt#1#2{%
+ \csname forestmath at if@lt@\forestmathresulttype\endcsname{#1}{#2}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathlt@#1#2#3{%
+ \csname forestmath at if@lt@#1\endcsname{#2}{#3}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathgt#1#2{%
+ \csname forestmath at if@lt@\forestmathresulttype\endcsname{#2}{#1}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathgt@#1#2#3{%
+ \csname forestmath at if@lt@#1\endcsname{#3}{#2}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmatheq#1#2{%
+ \csname forestmath at if@eq@\forestmathresulttype\endcsname{#1}{#2}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmatheq@#1#2#3{%
+ \csname forestmath at if@eq@#1\endcsname{#2}{#3}%
+ \forestmathtrue
+ \forestmathfalse}
+\def\forestmathmin{\forestmath at minmax{min}{\forestmathresulttype}}
+\def\forestmathmax{\forestmath at minmax{max}{\forestmathresulttype}}
+\def\forestmathmin@{\forestmath at minmax{min}}
+\def\forestmathmax@{\forestmath at minmax{max}}
+\def\forestmath at minmax#1#2#3#4{% #1=min/max, #2=type, #3,#4=args
+ \edef\forestmath at tempa{#3}%
+ \edef\forestmath at tempb{#4}%
+ \if\relax\detokenize\expandafter{\forestmath at tempa}\relax
+ \forestmath at minmax@one{#1}{#2}\forestmath at tempb
+ \else
+ \if\relax\detokenize\expandafter{\forestmath at tempb}\relax
+ \forestmath at minmax@one{#1}{#2}\forestmath at tempa
+ \else
+ \csname forestmath@#1\endcsname{#2}%
+ \fi
+ \fi
+}
+\def\forestmath at minmax@one#1#2#3{% #1=min/max, #2=type, #3 = the (possibly) non-empty arg
+ \ifcsname forestmath@#1 at one@#2\endcsname
+ \csname forestmath@#1 at one@#2\endcsname#3%
+ \else
+ \let\forestmathresult#3%
+ \fi
+}
+\def\forestmath at min@one at t#1{\let\forestmathresult\forest at empty}
+\def\forestmath at max@one at t#1{\let\forestmathresult#1}
+\def\forestmath at min@one at T#1{\let\forestmathresult#1}
+\def\forestmath at max@one at T#1{\let\forestmathresult\forest at empty}
+
+\def\forestmath at min#1{% #1 = type
+ \csname forestmath at if@lt@#1\endcsname\forestmath at tempa\forestmath at tempb
+ {\let\forestmathresult\forestmath at tempa}%
+ {\let\forestmathresult\forestmath at tempb}%
+}
+\def\forestmath at max#1{% #1 = type
+ \csname forestmath at if@lt@#1\endcsname\forestmath at tempa\forestmath at tempb
+ {\let\forestmathresult\forestmath at tempb}%
+ {\let\forestmathresult\forestmath at tempa}%
+}
\def\forest at sort#1#2#3#4#5{%
\let\forest at sort@cmp#1\relax
\let\forest at sort@let#2\relax
@@ -869,52 +1648,38 @@
\bracket at afterthought={}%
}
% full expansion expands precisely to the value
-\def\forestov#1{\expandafter\expandafter\expandafter\expandonce
- \pgfkeysvalueof{/forest/@node/\forest at cn/#1}}
+\def\forestov#1{\expandafter\expandonce\csname fRsT\forest at cn/#1\endcsname}
% full expansion expands all the way
-\def\forestove#1{\pgfkeysvalueof{/forest/@node/\forest at cn/#1}}
+\def\forestove#1{\csname fRsT\forest at cn/#1\endcsname}
% full expansion expands to the cs holding the value
-\def\forestom#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/\forest at cn/#1}}}
-\def\forestoget#1#2{\pgfkeysgetvalue{/forest/@node/\forest at cn/#1}{#2}}
-\def\forestolet#1#2{\pgfkeyslet{/forest/@node/\forest at cn/#1}{#2}}
-\def\forestocslet#1#2{%
- \edef\forest at marshal{%
- \noexpand\pgfkeyslet{/forest/@node/\forest at cn/#1}{\expandonce{\csname#2\endcsname}}%
- }\forest at marshal
-}
-\def\forestoset#1#2{\pgfkeyssetvalue{/forest/@node/\forest at cn/#1}{#2}}
-\def\forestoeset#1#2{%
- \edef\forest at option@temp{%
- \noexpand\pgfkeyssetvalue{/forest/@node/\forest at cn/#1}{#2}%
- }\forest at option@temp
-}
+\def\forestom#1{\expandonce{\csname fRsT\forest at cn/#1\endcsname}}
+\def\forestoget#1#2{\expandafter\let\expandafter#2\csname fRsT\forest at cn/#1\endcsname}
+\def\forestolet#1#2{\expandafter\let\csname fRsT\forest at cn/#1\endcsname#2}
+\def\forestoset#1#2{\expandafter\edef\csname fRsT\forest at cn/#1\endcsname{\unexpanded{#2}}}
+\def\forestoeset#1%#2
+ {\expandafter\edef\csname fRsT\forest at cn/#1\endcsname
+ %{#2}
+ }
\def\forestoappto#1#2{%
\forestoeset{#1}{\forestov{#1}\unexpanded{#2}}%
}
-\def\forestoifdefined#1#2#3{%
- \pgfkeysifdefined{/forest/@node/\forest at cn/#1}{#2}{#3}%
+\def\forestoifdefined#1%#2#3
+{%
+ \ifcsdef{fRsT\forest at cn/#1}%{#2}{#3}%
}
\let\forestoption\forestov
\let\foresteoption\forestove
-\def\forestOv#1#2{\expandafter\expandafter\expandafter\expandonce
- \pgfkeysvalueof{/forest/@node/#1/#2}}
-\def\forestOve#1#2{\pgfkeysvalueof{/forest/@node/#1/#2}}
+\def\forestOv#1#2{\expandafter\expandonce\csname fRsT#1/#2\endcsname}
+\def\forestOve#1#2{\csname fRsT#1/#2\endcsname}
% full expansion expands to the cs holding the value
-\def\forestOm#1#2{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/#1/#2}}}
-\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}}
-\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}}
-\def\forestOlet#1#2#3{\pgfkeyslet{/forest/@node/#1/#2}{#3}}
-\def\forestOcslet#1#2#3{%
- \edef\forest at marshal{%
- \noexpand\pgfkeyslet{/forest/@node/#1/#2}{\expandonce{\csname#3\endcsname}}%
- }\forest at marshal
+\def\forestOm#1#2{\expandonce{\csname fRsT#1/#2\endcsname}}
+\def\forestOget#1#2#3{\expandafter\let\expandafter#3\csname fRsT#1/#2\endcsname}
+\def\forestOlet#1#2#3{\expandafter\let\csname fRsT#1/#2\endcsname#3}
+\def\forestOset#1#2#3{\expandafter\edef\csname fRsT#1/#2\endcsname{\unexpanded{#3}}}
+\def\forestOeset#1#2%#3
+{\expandafter\edef\csname fRsT#1/#2\endcsname
+ % {#3}
}
-\def\forestOset#1#2#3{\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}}
-\def\forestOeset#1#2#3{%
- \edef\forestoption at temp{%
- \noexpand\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}%
- }\forestoption at temp
-}
\def\forestOappto#1#2#3{%
\forestOeset{#1}{#2}{\forestOv{#1}{#2}\unexpanded{#3}}%
}
@@ -927,8 +1692,9 @@
\def\forestOepreto#1#2#3{%
\forestOeset{#1}{#2}{#3\forestOv{#1}{#2}}%
}
-\def\forestOifdefined#1#2#3#4{%
- \pgfkeysifdefined{/forest/@node/#1/#2}{#3}{#4}%
+\def\forestOifdefined#1#2%#3#4
+{%
+ \ifcsdef{fRsT#1/#2}%{#3}{#4}%
}
\def\forestOletO#1#2#3#4{% option #2 of node #1 <-- option #4 of node #3
\forestOget{#3}{#4}\forestoption at temp
@@ -942,26 +1708,48 @@
\def\forestoleto#1#2{%
\forestoget{#2}\forestoption at temp
\forestolet{#1}\forestoption at temp}
+\def\forestRNOget#1#2{% #1=rn!option, #2 = receiving cs
+ \pgfutil at in@{.}{#1}%
+ \ifpgfutil at in@
+ \forestRNOget at rn#2#1\forest at END
+ \else
+ \forestoget{#1}#2%
+ \fi
+}
+\def\forestRNOget at rn#1#2.#3\forest at END{%
+ \forest at forthis{%
+ \forest at nameandgo{#2}%
+ \forestoget{#3}#1%
+ }%
+}
+\def\forestRNO at getvalueandtype#1#2#3{% #1=rn.option, #2,#3 = receiving css
+ \pgfutil at in@{.}{#1}%
+ \ifpgfutil at in@
+ \forestRNO at getvalueandtype@rn#2#3#1\forest at END
+ \else
+ \forestoget{#1}#2%
+ \pgfkeysgetvalue{/forest/#1/@type}#3%
+ \fi
+}
+\def\forestRNO at getvalueandtype@rn#1#2#3.#4\forest at END{%
+ % #1,#2=receiving css, #3=relative node name, #4=option name
+ \forest at forthis{%
+ \forest at nameandgo{#3}%
+ \forestoget{#4}#1%
+ }%
+ \pgfkeysgetvalue{/forest/#4/@type}#2%
+}
% full expansion expands precisely to the value
-\def\forestrv#1{\expandafter\expandafter\expandafter\expandonce
- \pgfkeysvalueof{/forest/@node/register/#1}}
+\def\forestrv#1{\expandafter\expandonce\csname fRsT/#1\endcsname}
% full expansion expands all the way
-\def\forestrve#1{\pgfkeysvalueof{/forest/@node/register/#1}}
+\def\forestrve#1{\csname fRsT/#1\endcsname}
% full expansion expands to the cs holding the value
-\def\forestrm#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/register/#1}}}
-\def\forestrget#1#2{\pgfkeysgetvalue{/forest/@node/register/#1}{#2}}
-\def\forestrlet#1#2{\pgfkeyslet{/forest/@node/register/#1}{#2}}
-\def\forestrcslet#1#2{%
- \edef\forest at marshal{%
- \noexpand\pgfkeyslet{/forest/@node/register/#1}{\expandonce{\csname#2\endcsname}}%
- }\forest at marshal
-}
-\def\forestrset#1#2{\pgfkeyssetvalue{/forest/@node/register/#1}{#2}}
-\def\forestreset#1#2{%
- \edef\forest at option@temp{%
- \noexpand\pgfkeyssetvalue{/forest/@node/register/#1}{#2}%
- }\forest at option@temp
-}
+\def\forestrm#1{\expandonce{\csname fRsT/#1\endcsname}}
+\def\forestrget#1#2{\expandafter\let\expandafter#2\csname fRsT/#1\endcsname}
+\def\forestrlet#1#2{\expandafter\let\csname fRsT/#1\endcsname#2}
+\def\forestrset#1#2{\expandafter\edef\csname fRsT/#1\endcsname{\unexpanded{#2}}}
+\def\forestreset#1%#2
+ {\expandafter\edef\csname fRsT/#1\endcsname}%{#2}
\def\forestrappto#1#2{%
\forestreset{#1}{\forestrv{#1}\unexpanded{#2}}%
}
@@ -968,8 +1756,9 @@
\def\forestrpreto#1#2{%
\forestreset{#1}{\unexpanded{#2}\forestrv{#1}}%
}
-\def\forestrifdefined#1#2#3{%
- \pgfkeysifdefined{/forest/@node/register/#1}{#2}{#3}%
+\def\forestrifdefined#1%#2#3
+{%
+ \ifcsdef{fRsT/#1}%{#2}{#3}%
}
\def\forestregister#1{\forestrv{#1}}
\def\foresteregister#1{\forestrve{#1}}
@@ -1498,7 +2287,12 @@
}
\NewDocumentCommand\forestdebugtypeouttrees{o}{%
\forestdebug at typeouttrees\forest at temp
- \typeout{\IfValueTF{#1}{#1: }{}\forest at temp}%
+ \typeout{%
+ \forestdebugtypeouttreesprefix
+ \IfValueTF{#1}{#1: }{}%
+ \detokenize\expandafter{\forest at temp}%
+ \forestdebugtypeouttreessuffix
+ }%
}
\def\forestdebug at typeouttrees#1{% #1 = cs to store the result
\begingroup
@@ -1514,12 +2308,12 @@
\expandafter\endgroup
\expandafter\edef\expandafter\forest at cn\expandafter{\forest at cn}%
\forestdebug at typeouttree@build
- \appto\forest at temp@message{\space}%
+ \appto\forest at temp@message{ }%
}%
}%
\repeat
\expandafter\endgroup
- \expandafter\edef\expandafter#1\expandafter{\forest at temp@message}%
+ \expandafter\def\expandafter#1\expandafter{\forest at temp@message}%
}
\def\forestdebug at typeouttrees@findroot{%
\let\forestdebug at typeouttrees@next\relax
@@ -1546,9 +2340,9 @@
\typeout{\IfValueTF{#1}{#1: }{}\forest at temp}%
}
\def\forestdebug at typeouttree@build{%
- \eappto\forest at temp@message{[\forest at cn%]
+ \eappto\forest at temp@message{[\forestdebugtypeouttreenodeinfo%]
\ifcsdef{forestdebug at typeouttree@used@\forest at cn}{*}{}%
- }%
+ }%
\ifcsdef{forestdebug at typeouttree@used@\forest at cn}{}{%
\csdef{forestdebug at typeouttree@used@\forest at cn}{}%
\forest at node@foreachchild{\forestdebug at typeouttree@build}%
@@ -1556,6 +2350,9 @@
\eappto\forest at temp@message{%[
]}%
}
+\def\forestdebugtypeouttreenodeinfo{\forest at cn}
+\def\forestdebugtypeouttreesprefix{}
+\def\forestdebugtypeouttreessuffix{}
\def\forest at declarehandler#1#2#3{%#1=handler for specific type,#2=option name,#3=default value
\pgfkeyssetvalue{/forest/#2}{#3}%
\appto\forest at node@init{\forestoinit{#2}}%
@@ -1635,6 +2432,7 @@
\pgfkeyssetvalue{#1/option at name}{#3}%
\pgfkeyssetvalue{#1+/option at name}{#3}%
\pgfkeyssetvalue{#2/+#3/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at generic % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at toks{##1}{#3}}%
}
\def\forest at declareautowrappedtoks@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix
@@ -1664,8 +2462,27 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}},
+ #2/where #3</.style n args={3}{for tree={#2/if #3<={##1}{##2}{##3}}},
+ #2/where #3>/.style n args={3}{for tree={#2/if #3>={##1}{##2}{##3}}},
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at dimen % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at dimen{##1}{#3}}%
}
\def\forest at declaredimen@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -1672,17 +2489,17 @@
\forest at declarereadonlydimen@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{%
#1/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\forestOlet{\forest at setter@node}{#3}\forest at temp
},
#1+/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestove{#3}
\advance\pgfutil at tempdima\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\pgfutil at tempdima}%
},
#1-/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestove{#3}
\advance\pgfutil at tempdima-\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\pgfutil at tempdima}%
@@ -1739,8 +2556,27 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestoget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}},
+ #2/where #3</.style n args={3}{for tree={#2/if #3<={##1}{##2}{##3}}},
+ #2/where #3>/.style n args={3}{for tree={#2/if #3>={##1}{##2}{##3}}},
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at count{##1}{#3}}%
}
\def\forest at declarecount@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -1747,29 +2583,29 @@
\forest at declarereadonlycount@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{
#1/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\forestOlet{\forest at setter@node}{#3}\forest at temp
},
#1+/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\advance\c at pgf@counta\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
},
#1-/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\advance\c at pgf@counta-\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
},
#1*/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\multiply\c at pgf@counta\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
},
#1:/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestove{#3}\relax
\divide\c at pgf@counta\forest at temp\relax
\forestOeset{\forest at setter@node}{#3}{\the\c at pgf@counta}%
@@ -1813,30 +2649,27 @@
\def\forest at declareboolean@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
\pgfkeysalso{%
#1/.code={%
- \ifstrequal{##1}{1}{%
- \forestOset{\forest at setter@node}{#3}{1}%
+ \forestmath at if{##1}{%
+ \def\forest at temp{1}%
}{%
- \ifstrequal{##1}{0}{%
- \forestOset{\forest at setter@node}{#3}{0}%
- }{%
- \pgfmathifthenelse{##1}{1}{0}%
- \forestOlet{\forest at setter@node}{#3}\pgfmathresult
- }%
+ \def\forest at temp{0}%
}%
+ \forestOlet{\forest at setter@node}{#3}\forest at temp
},
#1/.default=1,
#2/not #3/.code={\forestOset{\forest at setter@node}{#3}{0}},
#2/if #3/.code 2 args={%
\forestoget{#3}\forest at temp@option at value
- \ifnum\forest at temp@option at value=1
+ \ifnum\forest at temp@option at value=0
+ \pgfkeysalso{##2}%
+ \else
\pgfkeysalso{##1}%
- \else
- \pgfkeysalso{##2}%
\fi
},
#2/where #3/.style 2 args={for tree={#2/if #3={##1}{##2}}}
}%
\pgfkeyssetvalue{#1/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@attribute at count{##1}{#3}}%
}
\forestset{
@@ -1850,31 +2683,35 @@
\forest at declarehandler\forest at declarekeylist@handler{#1}{#2}%
},
declare readonly dimen/.code 2 args={%
- \pgfmathsetlengthmacro\forest at temp{#2}%
+ \forestmathsetlengthmacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declarereadonlydimen@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare dimen/.code 2 args={%
- \pgfmathsetlengthmacro\forest at temp{#2}%
+ \forestmathsetlengthmacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declaredimen@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare readonly count/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#2}%
+ \forestmathtruncatemacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declarereadonlycount@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare count/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#2}%
+ \forestmathtruncatemacro\forest at temp{#2}%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declarecount@handler{#1}}{\forest at temp}%
}\forest at marshal
},
declare boolean/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#2}%
+ \forestmath at if{#2}{%
+ \def\forest at temp{1}%
+ }{%
+ \def\forest at temp{0}%
+ }%
\edef\forest at marshal{%
\unexpanded{\forest at declarehandler\forest at declareboolean@handler{#1}}{\forest at temp}%
}\forest at marshal
@@ -1898,10 +2735,15 @@
\pgfkeysalso{\forest at handlers@wrap at currentpath/.expand once=\forest at wrapped@value}%
},
/handlers/.option/.code={%
- \edef\forest at marshal{%
- \noexpand\pgfkeysalso{\pgfkeyscurrentpath={\forestoption{#1}}}%
- }\forest at marshal
+ \edef\forest at temp{\pgfkeyscurrentpath}%
+ \expandafter\forest at handlers@option\expandafter{\forest at temp}{#1}%
},
+}
+\def\forest at handlers@option#1#2{%#1=pgfkeyscurrentpath,#2=relative node name
+ \forestRNOget{#2}\forest at temp
+ \pgfkeysalso{#1/.expand once={\forest at temp}}%
+}%
+\forestset{
/handlers/.register/.code={%
\edef\forest at marshal{%
\noexpand\pgfkeysalso{\pgfkeyscurrentpath={\forestregister{#1}}}%
@@ -1908,7 +2750,7 @@
}\forest at marshal
},
/handlers/.wrap pgfmath arg/.code 2 args={%
- \pgfmathparse{#2}\let\forest at wrap@arg at i\pgfmathresult
+ \forestmathparse{#2}\let\forest at wrap@arg at i\forestmathresult
\edef\forest at wrap@args{{\expandonce\forest at wrap@arg at i}}%
\def\forest at wrap@code##1{#1}%
% here we don't call \forest at wrap@pgfmath at args@@@wrapandpasson, as compat-2.0.2-wrappgfmathargs changes that to achieve the old, confusing state of affairs, which *didn't* apply at *1*-arg pgfmath wrapping
@@ -1916,8 +2758,8 @@
\expandafter\pgfkeysalso\expandafter{\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{\the\forest at temp@toks}}%
},
/handlers/.wrap 2 pgfmath args/.code n args={3}{%
- \pgfmathparse{#2}\let\forest at wrap@arg at i\pgfmathresult
- \pgfmathparse{#3}\let\forest at wrap@arg at ii\pgfmathresult
+ \forestmathparse{#2}\let\forest at wrap@arg at i\forestmathresult
+ \forestmathparse{#3}\let\forest at wrap@arg at ii\forestmathresult
\edef\forest at wrap@args{{\expandonce\forest at wrap@arg at i}{\expandonce\forest at wrap@arg at ii}}%
\def\forest at wrap@code##1##2{#1}%
\forest at wrap@pgfmath at args@@@wrapandpasson
@@ -1940,19 +2782,16 @@
/handlers/.wrap 8 pgfmath args/.code n args={9}{%
\forest at wrap@n at pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}{8}%
\forest at wrap@n at pgfmath@do{#1}{8}},
- /handlers/.process args/.code={%
- \forest at processargs#1\forest at eov\forest at END
- },
}
\def\forest at wrap@n at pgfmath@args#1#2#3#4#5#6#7#8#9{%
- \pgfmathparse{#1}\let\forest at wrap@arg at i\pgfmathresult
- \ifnum#9>1 \pgfmathparse{#2}\let\forest at wrap@arg at ii\pgfmathresult\fi
- \ifnum#9>2 \pgfmathparse{#3}\let\forest at wrap@arg at iii\pgfmathresult\fi
- \ifnum#9>3 \pgfmathparse{#4}\let\forest at wrap@arg at iv\pgfmathresult\fi
- \ifnum#9>4 \pgfmathparse{#5}\let\forest at wrap@arg at v\pgfmathresult\fi
- \ifnum#9>5 \pgfmathparse{#6}\let\forest at wrap@arg at vi\pgfmathresult\fi
- \ifnum#9>6 \pgfmathparse{#7}\let\forest at wrap@arg at vii\pgfmathresult\fi
- \ifnum#9>7 \pgfmathparse{#8}\let\forest at wrap@arg at viii\pgfmathresult\fi
+ \forestmathparse{#1}\let\forest at wrap@arg at i\forestmathresult
+ \ifnum#9>1 \forestmathparse{#2}\let\forest at wrap@arg at ii\forestmathresult\fi
+ \ifnum#9>2 \forestmathparse{#3}\let\forest at wrap@arg at iii\forestmathresult\fi
+ \ifnum#9>3 \forestmathparse{#4}\let\forest at wrap@arg at iv\forestmathresult\fi
+ \ifnum#9>4 \forestmathparse{#5}\let\forest at wrap@arg at v\forestmathresult\fi
+ \ifnum#9>5 \forestmathparse{#6}\let\forest at wrap@arg at vi\forestmathresult\fi
+ \ifnum#9>6 \forestmathparse{#7}\let\forest at wrap@arg at vii\forestmathresult\fi
+ \ifnum#9>7 \forestmathparse{#8}\let\forest at wrap@arg at viii\forestmathresult\fi
\edef\forest at wrap@args{%
{\expandonce\forest at wrap@arg at i}
\ifnum#9>1 {\expandonce\forest at wrap@arg at ii}\fi
@@ -1985,103 +2824,485 @@
\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{%
\the\forest at temp@toks}}%
}
-\newtoks\forest at processargs@result
-\newtoks\forest at processargs@current
-\newif\ifforest at processargs@append
-\def\forest at eov{\forest at eov}
-\def\forest at processargs#1#2\forest at END{% #1 = processing instructions, #2 = args
- \forest at processargs@result{}%
- \forest at processargs@current{}%
- \forest at processargs@appendfalse
- \forest at processargs@getins#1.\forest at END#2\forest at END
+\def\forest at process@catregime{} % filled by processor defs
+\forest at newarray\forest at process@left@ % processed args
+\forest at newarray\forest at process@right@ % unprocessed args
+\forest at newarray\forest at process@saved@ % used by instructions |S| and |U|
+\let\forest at process@savedtype\forestmathtype at none
+\forest at newglobalarray\forest at process@result@
+\newif\ifforest at process@returnarray@
+\def\forest at process#1#2#{% #1 = true/false (should we return an array?)
+ % #2 = processing instructions (if non-empty),
+ % (initial) args follow
+ \ifblank{#2}{\forest at process@a{#1}}{\forest at process@a{#1}{#2}}%
}
-\def\forest at processargs@maybeappend{%
- \ifforest at processargs@append
- \eapptotoks\forest at processargs@result{{\the\forest at processargs@current}}%
- \forest at processargs@current{}%
- \fi
+\Inline\def\forest at process@a#1#2{%
+ \begingroup
+ \forest at process@left at clear
+ \forest at process@right at clear
+ \forest at process@saved at clear
+ \let\forest at process@savedtype\forestmathtype at generic
+ \ExpandIfT{forestdebug}{%
+ \edef\forest at process@debug at args{\unexpanded{#2}}%
+ \typeout{[forest .process] Start "\unexpanded{#2}"}%
+ }%
+ \csname forest at process@returnarray@#1\endcsname
+ \def\forest at topextend@next{%
+ \forest at process@catregime
+ \endlinechar=-1
+ \scantokens{#2}%
+ \forest at process@finish
+ }%
+ \forest at process@right at topextend
}
-\def\forest at processargs@getins#1#2\forest at END#3\forest at END{% #1 = first instruction, #2 = rest of instructions, #3 = args
- \csname forest at processargs@ins@#1\endcsname#2\forest at END#3\forest at END
+\pgfkeys{%
+ /handlers/.process/.code={%
+ \forest at process{true}#1\forest at eov
+ \edef\forest at marshal{%
+ \noexpand\pgfkeysalso{\noexpand\pgfkeyscurrentpath=\forest at process@result at values}%
+ }\forest at marshal
+ },
+ /forest/copy command key={/handlers/.process}{/handlers/.process args},
}
-\csdef{forest at processargs@ins at .}\forest at END#1\forest at END{%
- \forest at processargs@maybeappend
- \forest at processargs@appremainingargs#1\forest at END
+\def\forest at process@finish{%
+ \ifforest at process@returnarray@
+ \forest at process@finish at array
+ \global\let\forest at process@result at type\forest at result@type at array
+ \else
+ \forest at process@finish at single
+ \fi
+ \ifforestdebugprocess\forest at process@debug at end\fi
+ \endgroup
}
-\def\forest at processargs@appremainingargs#1#2\forest at END{%
- \edef\forest at temp{\unexpanded{#1}}%
- \ifx\forest at temp\forest at eov
- \let\forest at processargs@next\forest at processargs@done
+\def\forest at process@finish at single{%
+ \edef\forest at temp{forest at process@finish at single@%
+ \the\numexpr\forest at process@left at N-\forest at process@left at M\relax
+ \the\numexpr\forest at process@right at N-\forest at process@right at M\relax
+ }%
+ \ifcsname\forest at temp\endcsname
+ \csname\forest at temp\endcsname
+ \global\let\forest at process@result\forest at temp
\else
- \apptotoks\forest at processargs@result{{#1}}%
- \let\forest at processargs@next\forest at processargs@appremainingargs
+ \forest at process@lengtherror
\fi
- \forest at processargs@next#2\forest at END
+ \global\let\forest at process@result at type\forestmathresulttype
}
-\def\forest at processargs@done#1\forest at END{%
- \pgfkeysalso{\pgfkeyscurrentpath/.expanded=\the\forest at processargs@result}%
+\csdef{forest at process@finish at single@10}{\forest at process@left at toppop\forest at temp}
+\csdef{forest at process@finish at single@01}{\forest at process@right at toppop\forest at temp}
+\def\forest at process@finish at array{%
+ \forest at process@result at clear
+ \forest at temp@count\forest at process@left at M\relax
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@left at N\relax
+ \forest at process@left at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@result at letappend\forest at temp
+ \advance\forest at temp@count1
+ \forest at repeat
+ \forest at temp@count\forest at process@right at M\relax
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@right at N\relax
+ \forest at process@right at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@result at letappend\forest at temp
+ \advance\forest at temp@count1
+ \forest at repeat
}
-\csdef{forest at processargs@ins at _}#1\forest at END#2#3\forest at END{% no processing
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \forest at processargs@current{#2}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\ifforestdebug
+ \let\forest at process@d\forest at process@b
+ \def\forest at process@b#1\forest at eov{% save and print initial arguments
+ \edef\forest at process@debug at args{\unexpanded{#1}}%
+ \typeout{[forest .process] Start "\unexpanded{#1}"}%
+ \forest at process@d#1\forest at eov
+ }
+\fi
+\def\forest at process@debug at end{%
+ \typeout{[forest .process] \space\space\space End "\expandonce{\forest at process@debug at args}" -> "\forest at process@left at values\forest at process@right at values"}%
}
-\csdef{forest at processargs@ins at x}#1\forest at END#2#3\forest at END{% expand
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \etotoks\forest at processargs@current{#2}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at process@lengtherror{%
+ \PackageError{forest}{%
+ The ".process" expression was expected to evaluate to a single argument,
+ but the result is \the\forest at process@result at N
+ \space items long.}{}%
}
-\csdef{forest at processargs@ins at o}#1\forest at END#2#3\forest at END{% expand once
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \expandafter\forest at processargs@current\expandafter{#2}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@processor#1{%
+ {%
+ \def\forest at dp@double##1{%
+ \gdef\forest at global@temp{\forest at def@processor@{#1}{##1}}%
+ }%
+ \let\\\forest at dp@double
+ \catcode`#1=13
+ \scantokens{\\#1}%
+ }%
+ \forest at global@temp
}
-\csdef{forest at processargs@ins at O}#1\forest at END#2#3\forest at END{% option
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \etotoks\forest at processargs@current{\forestoption{#2}}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@processor@#1#2{%
+ % #1 = instruction char (normal catcode), #2 = instruction char (active)
+ % #3 = default n (optional numeric arg, which precedes any other args;
+ % if the default is empty, this means no optional n)
+ % #4 = args spec,
+ % #5 = code
+ \eappto\forest at process@catregime{%
+ \unexpanded{\let#2}\expandonce{\csname forest at processor@#1\endcsname}%
+ \unexpanded{\catcode`#1=13 }%
+ }%
+ \def\forest at def@processor at inschar{#1}%
+ \forest at def@processor@@
}
-\csdef{forest at processargs@ins at R}#1\forest at END#2#3\forest at END{% register
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \etotoks\forest at processargs@current{\forestregister{#2}}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@processor@@#1{%
+ \ifstrempty{#1}{%
+ \forest at def@processor@@non
+ }{%
+ \def\forest at def@processor@@default at n{#1}%
+ \forest at def@processor@@n
+ }%
}
-\csdef{forest at processargs@ins at P}#1\forest at END#2#3\forest at END{% pgfmath expression
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \pgfmathparse{#2}%
- \expandafter\forest at processargs@current\expandafter{\pgfmathresult}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@processor@@non#1#2{% #1=args spec, #2=code
+ \csedef{forest at processor@\forest at def@processor at inschar}#1{%
+ \relax %% we need this (see above)
+ \unexpanded{#2}%
+ \expandafter\forest at def@processor at debuginfo\expandafter{%
+ \expandafter"\forest at def@processor at inschar"\ifstrempty{#1}{}{(#1)}}%
+ \ignorespaces
+ }%
}
-\csdef{forest at processargs@ins at +}#1\forest at END#2\forest at END{% join processors
- \forest at processargs@appendfalse
+\def\forest at def@processor@@n{%
+ \@ifnextchar*%
+ {\forest at temptrue\forest at def@processor@@n@}%
+ {\forest at tempfalse\forest at def@processor@@n@@}%
+}
+\def\forest at def@processor@@n@*{\forest at def@processor@@n@@}
+\def\forest at def@processor@@n@@#1#2{% #1=args spec, #2=code
+ \csedef{forest at processor@\forest at def@processor at inschar}{%
+ \relax %% we need this (see above)
+ \noexpand\forestprocess at get@n
+ {\forest at def@processor@@default at n}%
+ \expandonce{\csname forest at processor@\forest at def@processor at inschar @\endcsname}%
+ }%
+ \ifforest at temp
+ \csedef{forest at processor@\forest at def@processor at inschar @}{%
+ \noexpand\forest at repeat@n at times{\forest at process@n}{%
+ \expandonce{\csname forest at processor@\forest at def@processor at inschar @rep\endcsname}%
+ }%
+ }%
+ \fi
+ \edef\forest at temp{%
+ \forest at def@processor at inschar
+ \ifforest at temp\else\noexpand\the\forest at process@n\fi
+ "}%
+ \csedef{forest at processor@\forest at def@processor at inschar @\ifforest at temp rep\fi}#1{%
+ \unexpanded{#2}%
+ \expandafter\forest at def@processor at debuginfo\expandafter{%
+ \forest at temp
+ \ifstrempty{#1}{}{(#1)}}%
+ }%
+}
+\def\forest at def@processor at debuginfo#1{% #1 = instruction call
+ \ifforestdebug
+ \expandonce{\forest at processor@debuginfo at template{#1}}%
+ \fi
+}
+\def\forest at processor@debuginfo at template#1{%
+ \ifforestdebugprocess
+ \edef\forest at temp@left{\forest at process@left at values}%
+ \edef\forest at temp@right{\forest at process@right at values}%
+ \edef\forest at temp@saved{\forest at process@saved at values}%
+ \typeout{[forest .process]\space\space\space\space After #1: left="\expandonce{\forest at temp@left}", right="\expandonce{\forest at temp@right}", saved="\expandonce{\forest at temp@saved}", type=\forestmathresulttype}%
+ \fi
+}
+\newcount\forest at process@n
+\def\forestprocess at get@n#1#2{%
+ \def\forestprocess at default@n{#1}%
+ \let\forestprocess at after@get at n@#2%
+ \afterassignment\forestprocess at get@n@\forest at process@n=0%
+}
+\def\forestprocess at get@n@{%
+ \ifnum\forest at process@n=0
+ \forest at process@n\forestprocess at default@n\relax
+ \fi
+ \forestprocess at after@get at n@
+}
+\forest at def@processor{_}{1}*{}{% no processing, no type
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at letappend\forest at temp
+}
+\forest at def@processor{n}{1}*{}{% numexpr
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at esetappend{\number\numexpr\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{d}{1}*{}{% dimexpr
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at esetappend{\the\dimexpr\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at dimen
+}
+\forest at def@processor{P}{1}*{}{% pgfmath expression
+ \forest at process@right at bottompop\forest at temp
+ \pgfmathparse{\forest at temp}%
+ \forest at process@left at letappend\pgfmathresult
+ \let\forestmathresulttype\forestmathtype at unitless
+}
+\forest at def@processor{t}{1}*{}{% text
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at letappend\forest at temp
+ \let\forestmathresulttype\forestmathtype at textasc
+}
+\forest at def@processor{-}{}{}{% toggle ascending/descending
+ \forest at process@left at toppop\forestmathresult
+ \csname forest at processor@-@\forestmathresulttype\endcsname
+ \forest at process@left at letappend\forestmathresult
+}
+\cslet{forest at processor@-@\forestmathtype at generic}\relax
+\csdef{forest at processor@-@\forestmathtype at count}{%
+ \forestmathadd{\forestmathzero}{-\forestmathresult}}
+\csletcs{forest at processor@-@\forestmathtype at dimen}
+ {forest at processor@-@\forestmathtype at count}
+\csletcs{forest at processor@-@\forestmathtype at unitless}
+ {forest at processor@-@\forestmathtype at count}
+\csdef{forest at processor@-@\forestmathtype at textasc}{%
+ \let\forestmathresulttype\forestmathtype at textdesc}
+\csdef{forest at processor@-@\forestmathtype at textdesc}{%
+ \let\forestmathresulttype\forestmathtype at textasc}
+
+\forest at def@processor{c}{}{}{% to lowercase
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\lowercase\expandafter{\expandafter\def\expandafter\forest at temp\expandafter{\forest at temp}}%
+ \forest at process@left at letappend\forest at temp
+}
+\forest at def@processor{C}{}{}{% to uppercase
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\uppercase\expandafter{\expandafter\def\expandafter\forest at temp\expandafter{\forest at temp}}%
+ \forest at process@left at letappend\forest at temp
+}
+\forest at def@processor{x}{}{}{% expand
+ \forest at process@right at bottompop\forest at temp
+ \forest at process@left at esetappend{\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at generic
+}
+\forest at def@processor{o}{1}{}{% expand once (actually, \forest at count@n times)
+ \forest at process@right at bottompop\forest at temp
+ \forest at repeat@n at times{\forest at process@n}{%
+ \expandafter\expandafter\expandafter\def
+ \expandafter\expandafter\expandafter\forest at temp
+ \expandafter\expandafter\expandafter{\forest at temp}%
+ }%
+ \expandafter\forest at process@left at setappend\expandafter{\forest at temp}%
+ \let\forestmathresulttype\forestmathtype at generic
+}
+\forest at def@processor{O}{1}*{}{% option
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\forestRNO at getvalueandtype\expandafter{\forest at temp}\forest at tempvalue\forest at temp@type
+ \let\forestmathresulttype\forest at temp@type
+ \forest at process@left at letappend\forest at tempvalue
+}
+\forest at def@processor{R}{1}*{}{% register
+ \forest at process@right at bottompop\forest at temp
+ \forestrget{\forest at temp}\forest at tempvalue
+ \forest at process@left at letappend\forest at tempvalue
+ \pgfkeysgetvalue{/forest/\forest at temp/@type}\forest at temp@type
+ \let\forestmathresulttype\forest at temp@type
+}
+\forest at def@processor{+}{1}*{}{% join processors = pop one from result
+ \forest at process@left at toppop\forest at temp
+ \forest at process@right at letprepend\forest at temp
+}
+\forest at def@processor{u}{}{}{% ungroup: remove braces and leave in the argument list
+ \forest at process@right at bottompop\forest at temp
+ \forest at temparray@clear
+ \let\forestmathresulttype\forestmathtype at generic
+ \let\forest at topextend@next\forest at processor@u@
+ \expandafter\forest at temparray@topextend\forest at temp\forest at eov
+}
+\def\forest at processor@u@{%
+ \forest at loop
+ \ifnum\forest at temparray@N>0
+ \forest at temparray@toppop\forest at temp
+ \expandafter\forest at process@right at setprepend\expandafter{\expandafter{\forest at temp}}%
+ \forest at repeat
+}
+\def\forest at process@check at mn#1#2#3#4{%
+ % #1 = processor, #2 = given n, #3/#4 = lower/upper bound (inclusive)
+ \ifnum#3>#2\relax
+ \forest at process@check at n@error{#1}{#2}{#3<=}{<=#4}%
+ \else
+ \ifnum#4<#2\relax
+ \forest at process@check at n@error{#1}{#2}{#3<=}{<=#4}%
+ \fi
+ \fi
+}
+\def\forest at process@check at m#1#2#3{%
+ % #1 = processor, #2 = given n, #3 = lower bound (inclusive)
+ \ifnum#2<#3\relax
+ \forest at process@check at n@error{#1}{#2}{#3<=}{}%
+ \fi
+}
+\def\forest at process@check at n@error#1#2#3#4{%
+ \PackageError{forest}{'.process' instruction '#1' requires a numeric modifier #3n#4, but n="#2" was given.}{}%
+}
+\newif\ifforest at process@W
+\forest at def@processor{w}{1}{}{% consuming wrap: first test 1<=#1<=9
+ \forest at process@Wtrue
+ \forest at process@check at mn{w}{0\the\forest at process@n}{1}{9}%
+ \expandafter\forest at processor@wW@\expandafter{\the\forest at process@n}%
+}
+\forest at def@processor{W}{1}{}{% nonconsuming wrap: first test 1<=#1<=9
+ \forest at process@Wfalse
+ \forest at process@check at mn{W}{0\the\forest at process@n}{1}{9}%
+ \expandafter\forest at processor@wW@\expandafter{\the\forest at process@n}%
+}
+\def\forest at processor@wW@#1{%
+ \forest at process@left at checkindex{\forest at process@left at N-#1}%
\edef\forest at marshal{%
- \unexpanded{\forest at processargs@getins#1\forest at END}{\the\forest at processargs@current}\unexpanded{#2\forest at END}%
+ \edef\noexpand\forest at temp@args{%
+ \noexpand\forest at process@left at valuesfromrange
+ {\number\numexpr\forest at process@left at N-#1}%
+ {\the\forest at process@left at N}%
+ }%
}\forest at marshal
+ \ifforest at process@W
+ \advance\forest at process@left at N-#1\relax
+ \fi
+ \forest at process@right at bottompop\forest at temp@macrobody
+ \expandafter\forest at def@n\expandafter\forest at process@temp at macro\expandafter{\expandafter#1\expandafter}\expandafter{\forest at temp@macrobody}%
+ \expandafter\expandafter\expandafter\forest at process@left at setappend\expandafter\expandafter\expandafter{\expandafter\forest at process@temp at macro\forest at temp@args}%
+ \let\forestmathresulttype\forestmathtype at generic
}
-\csdef{forest at processargs@ins at r}#1\forest at END#2#3\forest at END{% reverse keylist
- % #1 = rest of ins, #2 = first arg, #3 = rest of args
- \forest at processargs@maybeappend
- \forest at processargs@current{}%
- \pgfqkeys{/forest}{split={#2}{,}{reverse at keylist}}%
- \forest at processargs@appendtrue
- \forest at processargs@getins#1\forest at END#3\forest at END
+\def\forest at def@n#1#2{\csname forest at def@n@#2\endcsname#1}
+\csdef{forest at def@n at 1}#1{\def#1##1}
+\csdef{forest at def@n at 2}#1{\def#1##1##2}
+\csdef{forest at def@n at 3}#1{\def#1##1##2##3}
+\csdef{forest at def@n at 4}#1{\def#1##1##2##3##4}
+\csdef{forest at def@n at 5}#1{\def#1##1##2##3##4##5}
+\csdef{forest at def@n at 6}#1{\def#1##1##2##3##4##5##6}
+\csdef{forest at def@n at 7}#1{\def#1##1##2##3##4##5##6##7}
+\csdef{forest at def@n at 8}#1{\def#1##1##2##3##4##5##6##7##8}
+\csdef{forest at def@n at 9}#1{\def#1##1##2##3##4##5##6##7##8##9}
+\forest at def@processor{s}{1}{}{%
+ \forest at temptrue % delete the originals
+ \expandafter\forest at processor@save\expandafter{%
+ \the\numexpr\forest at process@left at N-\forest at process@n}}
+\forest at def@processor{S}{1}{}{%
+ \forest at tempfalse % keep the originals
+ \expandafter\forest at processor@save\expandafter{%
+ \the\numexpr\forest at process@left at N-\forest at process@n}}
+\def\forest at processor@save#1{%
+ \forest at process@left at checkindex{#1}%
+ \forest at temp@count#1
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@left at N\relax
+ \forest at process@left at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@saved at letappend\forest at temp
+ \advance\forest at temp@count+1
+ \forest at repeat
+ \let\forest at process@savedtype\forestmathresulttype
+ \ifforest at temp
+ \forest at process@left at N=#1
+ \fi
}
+\forest at def@processor{l}{0}{}{%
+ \forest at temptrue
+ \forest at processor@U@@
+}
+\forest at def@processor{L}{0}{}{%
+ \forest at tempfalse
+ \forest at processor@U@@
+}
+
+\def\forest at processor@U@@{%
+ \ifnum\forest at process@n=0
+ \forest at process@n\forest at process@saved at N\relax
+ \fi
+ \expandafter\forest at processor@U@@@\expandafter{%
+ \the\numexpr\forest at process@saved at N-\forest at temp@count}%
+}
+\def\forest at processor@U@@@#1{%
+ \forest at temp@count#1
+ \forest at loop
+ \ifnum\forest at temp@count<\forest at process@saved at N\relax
+ \forest at process@saved at get@{\the\forest at temp@count}\forest at temp
+ \forest at process@left at letappend\forest at temp
+ \advance\forest at temp@count1
+ \forest at repeat
+ \let\forestmathresulttype\forest at process@savedtype
+ \ifforest at temp
+ \let\forest at process@savedtype\forest at result@type at any
+ \forest at process@saved at N#1
+ \fi
+}
+\forest at def@processor{&}{2}{}{% and
+ \def\forest at tempa{1}%
+ \forest at repeat@n at times{\forest at process@n}{%
+ \forest at process@left at bottompop\forest at tempb
+ \edef\forest at tempa{\ifnum10<\forest at tempa\forest at tempb\space 1\else0\fi}%
+ }%
+ \forest at process@left at esetappend{\forest at tempa}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{|}{2}{}{% or
+ \def\forest at tempa{0}%
+ \forest at repeat@n at times{\forest at process@n}{%
+ \forest at process@left at bottompop\forest at tempb
+ \edef\forest at tempa{\ifnum0=\forest at tempa\forest at tempb\space 0\else1\fi}%
+ }%
+ \forest at process@left at esetappend{\forest at tempa}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{!}{}{}{% not
+ \forest at process@left at toppop\forest at temp
+ \forest at process@left at esetappend{\ifnum0=\forest at temp\space 1\else0\fi}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{?}{}{}{%
+ \forest at process@left at toppop\forest at temp
+ \forest at process@right at bottompop\forest at tempa
+ \forest at process@right at bottompop\forest at tempb
+ \ifnum\forest at temp=0
+ \forest at process@right at letprepend\forest at tempb
+ \else
+ \forest at process@right at letprepend\forest at tempa
+ \fi
+ \let\forestmathresulttype\forestmathtype at generic
+}
+\forest at def@processor{=}{}{}{%
+ \forest at process@left at toppop\forest at tempa
+ \forest at process@left at toppop\forest at tempb
+ \forest at process@left at esetappend{\ifx\forest at tempa\forest at tempb 1\else0\fi}%
+ \let\forestmathresulttype\forestmathtype at count
+}
+\forest at def@processor{<}{}{}{%
+ \forest at process@left at toppop\forest at tempb
+ \forest at process@left at toppop\forest at tempa
+ \ifx\forestmathresulttype\forestmathtype at generic
+ \forest at cmp@error\forest at tempa\forest at tempb
+ \else
+ \forestmathlt{\forest at tempa}{\forest at tempb}%
+ \forest at process@left at esetappend{\forestmathresult}%
+ \fi
+}
+\forest at def@processor{>}{}{}{%
+ \forest at process@left at toppop\forest at tempb
+ \forest at process@left at toppop\forest at tempa
+ \ifx\forestmathresulttype\forestmathtype at generic
+ \forest at cmp@error\forest at tempa\forest at tempb
+ \else
+ \forestmathgt{\forest at tempa}{\forest at tempb}%
+ \forest at process@left at esetappend{\forestmathresult}%
+ \fi
+}
+\forest at def@processor{r}{}{}{% reverse keylist
+ \forest at process@right at bottompop\forest at temp
+ \expandafter\forest at processor@r@\expandafter{\forest at temp}%
+}
+\def\forest at processor@r@#1{%
+ \forest at temp@toks{}%
+ \def\forest at tempcomma{}%
+ \pgfqkeys{/forest}{split={#1}{,}{process at rk}}%
+ \forest at process@left at esetappend{\the\forest at temp@toks}%
+ \let\forestmathresulttype\forestmathtype at generic
+}
\forestset{%
- reverse at keylist/.code={%
- \epretotoks\forest at processargs@current{#1,}%
- },
+ process at rk/.code={%
+ \epretotoks\forest at temp@toks{#1\forest at tempcomma}%
+ \def\forest at tempcomma{,}%
+ }%
}
\def\forest at pgfmathhelper@register at toks#1#2{% #1 is discarded: it is present only for analogy with options
\forestrget{#2}\pgfmathresult
@@ -2088,14 +3309,13 @@
}
\def\forest at pgfmathhelper@register at dimen#1#2{%
\forestrget{#2}\forest at temp
- \pgfmathparse{+\forest at temp}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}
\def\forest at pgfmathhelper@register at count#1#2{%
- \forestrget{#2}\forest at temp
- \pgfmathtruncatemacro\pgfmathresult{\forest at temp}%
+ \forestrget{#2}\pgfmathresult
}
\def\forest at declareregisterhandler#1#2{%#1=handler for specific type,#2=option name
- \pgfkeyssetvalue{/forest/#2/node at or@reg}{register}%
+ \pgfkeyssetvalue{/forest/#2/node at or@reg}{}% empty = register (node id=node)
\forest at convert@others at to@underscores{#2}\forest at pgfmathoptionname
\edef\forest at marshal{%
\noexpand#1{/forest/#2}{/forest}{#2}{\forest at pgfmathoptionname}%
@@ -2166,6 +3386,7 @@
\pgfkeyssetvalue{#1/option at name}{#3}%
\pgfkeyssetvalue{#1+/option at name}{#3}%
\pgfkeyssetvalue{#2/+#3/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at generic % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at toks{##1}{#3}}%
}
\def\forest at declareautowrappedtoksregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix
@@ -2190,7 +3411,24 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifdim\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at dimen % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at dimen{##1}{#3}}%
}
\def\forest at declaredimenregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -2197,17 +3435,17 @@
\forest at declarereadonlydimenregister@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{%
#1/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\forestrlet{#3}\forest at temp
},
#1+/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestrve{#3}
\advance\pgfutil at tempdima\forest at temp\relax
\forestreset{#3}{\the\pgfutil at tempdima}%
},
#1-/.code={%
- \pgfmathsetlengthmacro\forest at temp{##1}%
+ \forestmathsetlengthmacro\forest at temp{##1}%
\pgfutil at tempdima=\forestrve{#3}
\advance\pgfutil at tempdima-\forest at temp\relax
\forestreset{#3}{\the\pgfutil at tempdima}%
@@ -2264,7 +3502,24 @@
\pgfkeysalso{##3}%
\fi
},
+ #2/if #3</.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value>##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
+ #2/if #3>/.code n args={3}{%
+ \forestrget{#3}\forest at temp@option at value
+ \ifnum\forest at temp@option at value<##1\relax
+ \pgfkeysalso{##3}%
+ \else
+ \pgfkeysalso{##2}%
+ \fi
+ },
}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at count{##1}{#3}}%
}
\def\forest at declarecountregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
@@ -2271,29 +3526,29 @@
\forest at declarereadonlycountregister@handler{#1}{#2}{#3}{#4}%
\pgfkeysalso{
#1/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\forestrlet{#3}\forest at temp
},
#1+/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\advance\c at pgf@counta\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
},
#1-/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\advance\c at pgf@counta-\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
},
#1*/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\multiply\c at pgf@counta\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
},
#1:/.code={%
- \pgfmathtruncatemacro\forest at temp{##1}%
+ \forestmathtruncatemacro\forest at temp{##1}%
\c at pgf@counta=\forestrve{#3}\relax
\divide\c at pgf@counta\forest at temp\relax
\forestreset{#3}{\the\c at pgf@counta}%
@@ -2337,16 +3592,13 @@
\def\forest at declarebooleanregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname
\pgfkeysalso{%
#1/.code={%
- \ifstrequal{##1}{1}{%
- \forestrset{#3}{1}%
+ \ifcsdef{forest at bh@\detokenize{##1}}{%
+ \letcs\forest at temp{forest at bh@\detokenize{##1}}%
}{%
- \ifstrequal{##1}{0}{%
- \forestrset{#3}{0}%
- }{%
- \pgfmathifthenelse{##1}{1}{0}%
- \forestrlet{#3}\pgfmathresult
- }%
+ \forestmathtruncatemacro\forest at temp{##1}%
+ \ifx\forest at temp0\else\def\forest at temp{1}\fi
}%
+ \forestrlet{#3}\forest at temp
},
#1/.default=1,
#2/not #3/.code={\forestrset{#3}{0}},
@@ -2360,6 +3612,7 @@
},
}%
\pgfkeyssetvalue{#1/option at name}{#3}%
+ \pgfkeyslet{#1/@type}\forestmathtype at count % for .process & co
\pgfmathdeclarefunction{#4}{1}{\forest at pgfmathhelper@register at count{##1}{#3}}%
}
\forestset{
@@ -2526,13 +3779,18 @@
preamble'={},
declare autowrapped toks={content}{},
% #1 = which option to split, #2 = separator (one char!), #3 = receiving options
- %%% begin listing region: split_option
- split option/.style n args=3{split/.process args={O}{#1}{#2}{#3}}
- %%% end listing region: split_option
- ,
- split register/.style n args=3{% #1 = which register to split, #2 = separator (one char!), #3 = receiving options
- split/.process args={R}{#1}{#2}{#3},
+ split option/.code n args=3{%
+ \forestRNOget{#1}\forest at temp
+ \edef\forest at marshal{%
+ \noexpand\pgfkeysalso{split={\expandonce{\forest at temp}}\unexpanded{{#2}{#3}}}%
+ }\forest at marshal
},
+ split register/.code n args=3{% #1 = which register to split, #2 = separator (one char!), #3 = receiving options
+ \forestrget{#1}\forest at temp
+ \edef\forest at marshal{%
+ \noexpand\pgfkeysalso{split={\expandonce{\forest at temp}}\unexpanded{{#2}{#3}}}%
+ }\forest at marshal
+ },
TeX={%
\def\forest at split@sourcevalues{}%
\def\forest at split@sourcevalue{}%
@@ -2729,7 +3987,7 @@
get node boundary/.code={%
\forestoget{@boundary}\forest at node@boundary
\def#1{}%
- \forest at extendpath#1\forest at node@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}%
+ \forest at extendpath#1\forest at node@boundary{\pgfqpoint{\forestove{x}}{\forestove{y}}}%
},
% get min l tree boundary/.code={%
% \forest at get@tree at boundary{negative}{\the\numexpr\forestove{grow}-90\relax}#1},
@@ -2785,7 +4043,7 @@
\def\forest at get@tree at boundary#1#2#3{%#1=pos/neg,#2=grow,#3=receiving cs
\def#3{}%
\forest at node@getedge{#1}{#2}\forest at temp@boundary
- \forest at extendpath#3\forest at temp@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}%
+ \forest at extendpath#3\forest at temp@boundary{\pgfqpoint{\forestove{x}}{\forestove{y}}}%
}
\def\forest at setter@node{\forest at cn}%
\def\forest at relatednode@option at compat@ignoreinvalidsteps#1{#1}
@@ -2808,33 +4066,31 @@
\forestset{
for tree'/.style 2 args={#1,for children={for tree'={#1}{#2}},#2},
if/.code n args={3}{%
- \pgfmathparse{#1}%
- \ifnum\pgfmathresult=0
+ \forestmathtruncatemacro\forest at temp{#1}%
+ \ifnum\forest at temp=0
\@escapeif{\pgfkeysalso{#3}}%
\else
\@escapeif{\pgfkeysalso{#2}}%
\fi
},
+ %LaTeX if/.code n args={3}{#1{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}},
if nodewalk valid/.code n args={3}{%
- \edef\forest at marshal{%
- \unexpanded{\forest at forthis{%
- \forest at nodewalk{%
- on invalid={fake}{#1},
- TeX={\global\let\forest at global@temp\forest at cn}
- }{}%
- }%
- \def\forest at cn}{\forest at cn}\unexpanded{%
- \ifnum\forest at global@temp=0
- \@escapeif{\pgfkeysalso{#3}}%
- \else
- \@escapeif{\pgfkeysalso{#2}}%
- \fi}%
- }\forest at marshal
+ \forest at forthis{%
+ \forest at configured@nodewalk{independent}{inherited}{fake}{%
+ #1,
+ TeX={\global\let\forest at global@temp\forest at cn}
+ }{}%
+ }%
+ \ifnum\forest at global@temp=0
+ \@escapeif{\pgfkeysalso{#3}}%
+ \else
+ \@escapeif{\pgfkeysalso{#2}}%
+ \fi
},
if nodewalk empty/.code n args={3}{%
\forest at forthis{%
- \forest at nodewalk{%
- on invalid={fake}{#1},
+ \forest at configured@nodewalk{independent}{independent}{fake}{%
+ #1,
TeX={\global\let\forest at global@temp\forest at nodewalk@n},
}{}%
}%
@@ -2844,11 +4100,18 @@
\@escapeif{\pgfkeysalso{#3}}%
\fi
},
+ if current nodewalk empty/.code 2 args={%
+ \ifnum\forest at nodewalk@n=0
+ \@escapeif{\pgfkeysalso{#1}}%
+ \else
+ \@escapeif{\pgfkeysalso{#2}}%
+ \fi
+ },
where/.style n args={3}{for tree={if={#1}{#2}{#3}}},
where nodewalk valid/.style n args={3}{for tree={if nodewalk valid={#1}{#2}{#3}}},
where nodewalk empty/.style n args={3}{for tree={if nodewalk empty={#1}{#2}{#3}}},
repeat/.code 2 args={%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\expandafter\forest at repeatkey\expandafter{\forest at temp}{#2}%
},
until/.code 2 args={%
@@ -2855,7 +4118,7 @@
\ifstrempty{#1}{%
\forest at untilkey{\ifnum\forest at cn=0\else\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at untilkey{\pgfmathifthenelse{#1}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at untilkey{\forestmath at if{#1}{\forestloopbreak}{}}{#2}%
}%
},
while/.code 2 args={%
@@ -2862,7 +4125,7 @@
\ifstrempty{#1}{%
\forest at untilkey{\ifnum\forest at cn=0\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at untilkey{\pgfmathifthenelse{not(#1)}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at untilkey{\forestmath at if{#1}{}{\forestloopbreak}}{#2}%
}%
},
do until/.code 2 args={%
@@ -2869,7 +4132,7 @@
\ifstrempty{#1}{%
\forest at dountilkey{\ifnum\forest at cn=0\else\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at dountilkey{\pgfmathifthenelse{#1}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at dountilkey{\forestmath at if{#1}{\forestloopbreak}{}}{#2}%
}%
},
do while/.code 2 args={%
@@ -2876,7 +4139,7 @@
\ifstrempty{#1}{%
\forest at dountilkey{\ifnum\forest at cn=0\relax\forestloopbreak\fi}{on invalid={fake}{#2}}%
}{%
- \forest at dountilkey{\pgfmathifthenelse{not(#1)}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}%
+ \forest at dountilkey{\forestmath at if{#1}{}{\forestloopbreak}}{#2}%
}%
},
until nodewalk valid/.code 2 args={%
@@ -2981,49 +4244,169 @@
\forest at aggregate@pgfmathpostparse at macro
}
\let\forest at aggregate@pgfmathpostparse\relax
-\pgfkeys{
+\forestset{
/handlers/.aggregate/.code n args=4{%
- % #1 = start value
- % #2 = pgfmath expression for every step
- % #3 = pgfmath expression for after walk
+ % #1 = start value (forestmath)
+ % #2 = forestmath expression that calculates "aggregate result" at each step
+ % #3 = forestmath expression that calculates "aggregate result" at the end of the nodewalk
% #4 = nodewalk
- \edef\forest at marshal{%
- \unexpanded{\forest at aggregate{#1}{#2}{#3}{#4}}{\pgfkeyscurrentpath}%
- }\forest at marshal
+ \forest at aggregate@handler{\forest at aggregate@generic{#1}{#2}{#3}{#4}}%
},
- /handlers/.sum/.style 2 args={/handlers/.aggregate={0}{(##1)+(#1)}{##1}{#2}},
- /handlers/.count/.style={/handlers/.aggregate={0}{1+(##1)}{##1}{#1}},
- /handlers/.average/.style 2 args={/handlers/.aggregate={0}{(##1)+(#1)}{##1/\forestregister{aggregate n}}{#2}},
- /handlers/.product/.style 2 args={/handlers/.aggregate={1}{(#1)*(##1)}{##1}{#2}},
- /handlers/.min/.style 2 args={/handlers/.aggregate={}{min(#1,##1)}{##1}{#2}},
- /handlers/.max/.style 2 args={/handlers/.aggregate={}{max(#1,##1)}{##1}{#2}},
- /forest/declare count register={aggregate n},
+ /handlers/.sum/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@sum{#1}{#2}}%
+ },
+ /handlers/.count/.code={% #1=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@count{#1}}%
+ },
+ /handlers/.average/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@average{#1}{#2}}%
+ },
+ /handlers/.product/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@product{#1}{#2}}%
+ },
+ /handlers/.min/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@min{#1}{#2}}%
+ },
+ /handlers/.max/.code 2 args={% #1=forestmath, #2=nodewalk
+ \forest at aggregate@handler{\forest at aggregate@max{#1}{#2}}%
+ },
+ declare count register={aggregate n},
+ declare toks register={aggregate value},
+ declare toks register={aggregate result},
+ aggregate result={},
}
-
-\def\forest at aggregate#1#2#3#4#5{%
- % #5 = current path
- \def\forest at aggregate@result{#1}%
- \forest at forthis{%
- \forestrset{aggregate n}{0}%
- \forest at nodewalk{#4}{%
- TeX={%
- \forestreset{aggregate n}{\number\numexpr\forestrv{aggregate n}+1}%
- \def\forest at marshal##1{\pgfmathparse{#2}}%
- \expandafter\forest at marshal\expandafter{\forest at aggregate@result}%
- \let\forest at aggregate@result\pgfmathresult
- }%
- }{}%
+\def\forest at aggregate@handler#1{%
+ \edef\forest at marshal{%
+ \unexpanded{%
+ #1%
+ }{%
+ \noexpand\pgfkeysalso{\pgfkeyscurrentpath/.register=aggregate result}%
}%
- \def\forest at marshal##1{\pgfmathparse{#3}}%
- \expandafter\forest at marshal\expandafter{\forest at aggregate@result}%
- \let\forest at aggregate@result\pgfmathresult
- \let\forest at temp@pgfmathpostparse\pgfmathpostparse
- \let\pgfmathpostparse\forest at aggregate@pgfmathpostparse
- \pgfmathqparse{\forest at aggregate@result pt}%
- \let\pgfmathpostparse\forest at temp@pgfmathpostparse
- \let\forest at aggregate@result\pgfmathresult
- \pgfkeysalso{#5/.expand once=\forest at aggregate@result}%
+ }\forest at marshal
}
+\def\forest at aggregate@pgfmathfunction at finish{%
+ \forestrget{aggregate result}\pgfmathresult
+}
+\pgfmathdeclarefunction{aggregate}{4}{%
+ \forest at aggregate@generic{#1}{#2}{#3}{#4}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_count}{1}{%
+ \forest at aggregate@sum{#1}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_sum}{2}{%
+ \forest at aggregate@sum{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_product}{2}{%
+ \forest at aggregate@product{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_average}{2}{%
+ \forest at aggregate@average{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_min}{2}{%
+ \forest at aggregate@min{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\pgfmathdeclarefunction{aggregate_max}{2}{%
+ \forest at aggregate@max{#1}{#2}%
+ \forest at aggregate@pgfmathfunction at finish
+}
+\def\forest at aggregate#1#2#3#4#5#6{% #1...#5=real args,
+ % #6=what to do with |aggregate result| register
+ % #1 = start value (forestmath)
+ % #2 = forestmath expression that calculates "aggregate current" at each step
+ % #3 = forestmath expression that calculates "aggregate result" at each step
+ % #4 = forestmath expression that calculates "aggregate result" at the end of the nodewalk
+ % #5 = nodewalk
+ \forest at saveandrestoreregister{aggregate result}{%
+ \forest at saveandrestoreregister{aggregate n}{%
+ \forest at aggregate@{#1}{#2}{#3}{#4}{#5}%
+ #6%
+ }%
+ }%
+}
+\def\forest at aggregate@generic#1#2#3#4{\forest at aggregate
+ {\forestmathparse{#1}}%
+ {}%
+ {\forestmathparse{#2}}%
+ {\forestmathparse{#3}}%
+ {#4}%
+}
+\def\forest at aggregate@sum#1#2{\forest at aggregate
+ {\forestmath at convert@fromto\forestmathtype at count\forestmathtype at generic{0}}%
+ {\forestmathparse{#1}}%
+ {\forestmathadd{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@count#1{\forest at aggregate
+ {\def\forestmathresult{1}}%
+ {\def\forestmathresult{1}}%
+ {\edef\forestmathresult{\the\numexpr\forestregister{aggregate result}+1}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#1}%
+}
+\def\forest at aggregate@average#1#2{\forest at aggregate
+ {\forestmath at convert@fromto\forestmathtype at count\forestmathtype at generic{0}}%
+ {\forestmathparse{#1}}%
+ {\forestmathadd{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestmathdivide at P{\forestregister{aggregate result}}{\forestregister{aggregate n}}}%
+ {#2}%
+}
+\def\forest at aggregate@product#1#2{\forest at aggregate
+ {\forestmath at convert@fromto\forestmathtype at count\forestmathtype at generic{1}}%
+ {\forestmathparse{#1}}%
+ {\forestmathmultiply{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@min#1#2{\forest at aggregate
+ {\def\forestmathresult{}}%
+ {\forestmathparse{#1}}%
+ {\forestmathmin{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@max#1#2{\forest at aggregate
+ {\def\forestmathresult{}}%
+ {\forestmathparse{#1}}%
+ {\forestmathmax{\forestregister{aggregate value}}{\forestregister{aggregate result}}}%
+ {\forestrget{aggregate result}\forestmathresult}%
+ {#2}%
+}
+\def\forest at aggregate@#1#2#3#4#5{%
+ % #1 = start value (forestmath)
+ % #2 = forestmath expression that calculates "aggregate current" at each step
+ % #3 = forestmath expression that calculates "aggregate result" at each step
+ % #4 = forestmath expression that calculates "aggregate result" at the end of the nodewalk
+ % #5 = nodewalk
+ #1%
+ \forestrlet{aggregate result}\forestmathresult
+ \forestrset{aggregate value}{}%
+ \forestrset{aggregate n}{0}%
+ \forest at forthis{%
+ \forest at nodewalk{#5}{%
+ TeX={%
+ \forestreset{aggregate n}{\number\numexpr\forestrv{aggregate n}+1}%
+ #2%
+ \forestrlet{aggregate value}\forestmathresult
+ #3%
+ \forestrlet{aggregate result}\forestmathresult
+ }%
+ }{}%
+ }%
+ #4%
+ \let\forest at temp@pgfmathpostparse\pgfmathpostparse
+ \let\pgfmathpostparse\forest at aggregate@pgfmathpostparse
+ \forestmath at convert@to\forestmathtype at dimen{\forestmathresult}
+ \pgfmathqparse{\forestmathresult}%
+ \let\pgfmathpostparse\forest at temp@pgfmathpostparse
+ \forestrlet{aggregate result}\pgfmathresult
+}
\pgfmathdeclarefunction{strequal}{2}{%
\ifstrequal{#1}{#2}{\def\pgfmathresult{1}}{\def\pgfmathresult{0}}%
}
@@ -3038,7 +4421,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{min at s}}%
+ \edef\forest at temp{\forestove{min at s}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\pgfmathdeclarefunction{min_l}{2}{% #1 = node, #2 = context node (for growth rotation)
@@ -3045,7 +4429,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{min at l}}%
+ \edef\forest at temp{\forestove{min at l}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\pgfmathdeclarefunction{max_s}{2}{% #1 = node, #2 = context node (for growth rotation)
@@ -3052,7 +4437,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{max at s}}%
+ \edef\forest at temp{\forestove{max at s}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\pgfmathdeclarefunction{max_l}{2}{% #1 = node, #2 = context node (for growth rotation)
@@ -3059,7 +4445,8 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\forest at compute@minmax at ls{#2}%
- \pgfmathsetmacro\pgfmathresult{\forestove{max at l}}%
+ \edef\forest at temp{\forestove{max at l}}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
}%
}
\def\forest at compute@minmax at ls#1{% #1 = nodewalk; in the context of which node?
@@ -3067,7 +4454,7 @@
\pgftransformreset
\forest at forthis{%
\forest at nameandgo{#1}%
- \pgftransformrotate{-\forestove{grow}}%
+ \forest at pgfqtransformrotate{-\forestove{grow}}%
}%
\forestoget{min x}\forest at temp@minx
\forestoget{min y}\forest at temp@miny
@@ -3116,10 +4503,10 @@
\forest at forthis{%
\forest at nameandgo{#1}%
\ifnum\forest at cn=0
- \def\pgfmathresult{0pt}%
+ \def\pgfmathresult{0}%
\else
\forestoget{#2}\forest at temp
- \pgfmathparse{+\forest at temp}%
+ \edef\pgfmathresult{\expandafter\Pgf at geT\forest at temp}%
\fi
}%
}
@@ -3129,8 +4516,7 @@
\ifnum\forest at cn=0
\def\pgfmathresult{0}%
\else
- \forestoget{#2}\forest at temp
- \pgfmathtruncatemacro\pgfmathresult{\forest at temp}%
+ \forestoget{#2}\pgfmathresult
\fi
}%
}
@@ -3171,21 +4557,30 @@
\def\forest at nodewalk@config at history@inherited at before{}
\let\forest at nodewalk@config at history@inherited at after\forest at nodewalk@config at history@independent at after
\def\forest at nodewalk#1#2{% #1 = nodewalk, #2 = every step keylist
- \def\forest at nodewalk@config at everystep@method{independent}%
- \def\forest at nodewalk@config at history@method{independent}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at Nodewalk{#1}{#2}%
- }%
+ \forest at configured@nodewalk{independent}{independent}{inherited}{#1}{#2}%
}
+\def\forest at configured@nodewalk#1#2#3#4#5{%
+ % #1 = every step method, #2 = history method, #3 = on invalid
+ % #4 = nodewalk, #5 = every step keylist
+ \def\forest at nodewalk@config at everystep@method{#1}%
+ \def\forest at nodewalk@config at history@method{#2}%
+ \def\forest at nodewalk@config at oninvalid{#3}%
+ \forest at Nodewalk{#4}{#5}%
+}
+\def\forest at nodewalk@oninvalid at inherited@text{inherited}
\def\forest at Nodewalk#1#2{% #1 = nodewalk, #2 = every step keylist
+ \ifx\forest at nodewalk@config at oninvalid\forest at nodewalk@oninvalid at inherited@text
+ \edef\forest at nodewalk@config at oninvalid{\forest at nodewalk@oninvalid}%
+ \fi
\edef\forest at marshal{%
\noexpand\pgfqkeys{/forest/nodewalk}{\unexpanded{#1}}%
\csname forest at nodewalk@config at everystep@\forest at nodewalk@config at everystep@method @after\endcsname
\csname forest at nodewalk@config at history@\forest at nodewalk@config at history@method @after\endcsname
+ \edef\noexpand\forest at nodewalk@oninvalid{\forest at nodewalk@oninvalid}%
}%
\csname forest at nodewalk@config at everystep@\forest at nodewalk@config at everystep@method @before\endcsname{#2}%
\csname forest at nodewalk@config at history@\forest at nodewalk@config at history@method @before\endcsname
+ \edef\forest at nodewalk@oninvalid{\forest at nodewalk@config at oninvalid}%
\forest at nodewalk@fakefalse
\forest at marshal
}
@@ -3205,25 +4600,27 @@
\def\forest at nodewalk@oninvalid{error}
\def\forest at nodewalk@makestep{%
\ifnum\forest at cn=0
- \csname forest at nodewalk@makestep at oninvalid@\forest at nodewalk@config at oninvalid\endcsname
+ \csname forest at nodewalk@makestep at oninvalid@\forest at nodewalk@oninvalid\endcsname
\else
\forest at nodewalk@makestep@
\fi
}
-\def\forest at nodewalk@makestep at oninvalid@step{\forest at nodewalk@makestep@}
+\csdef{forest at nodewalk@makestep at oninvalid@error if real}{\ifforest at nodewalk@fake\expandafter\forest at nodewalk@makestep@\else\expandafter\forest at nodewalk@makestep at oninvalid@error\fi}
+\csdef{forest at nodewalk@makestep at oninvalid@last valid}{%
+ \forest at nodewalk@tolastvalid
+ \ifforestdebugnodewalks\forest at nodewalk@makestep at invalidtolastvalid@debug\fi}%
\def\forest at nodewalk@makestep at oninvalid@error{\PackageError{forest}{nodewalk stepped to the invalid node\MessageBreak nodewalk stack: "\forest at nodewalk@currentstepname"}{}}%
\let\forest at nodewalk@makestep at oninvalid@fake\relax
\def\forest at nodewalk@makestep at oninvalid@compatfake{%
- \forest at deprecated{last step in stack "\forest at nodewalk@currentstepname", which stepped on an invalid node; enabled by "compat=ignoreinvalidsteps". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}%
+ \forest at deprecated{last step in stack "\forest at nodewalk@currentstepname", which stepped on an invalid node; enabled by "compat=1.0-forstep". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}%
}%
-\def\forest at nodewalk@makestep at oninvalid@inherited{\csname forest at nodewalk@makestep at oninvalid@\forest at nodewalk@oninvalid\endcsname}
\def\forest at nodewalk@makestep@{%
+ \ifforestdebugnodewalks\forest at nodewalk@makestep at debug\fi
\ifforest at nodewalk@fake
\else
\edef\forest at nodewalk@n{\number\numexpr\forest at nodewalk@n+1}%
\epreto\forest at nodewalk@historyback{\forest at cn,}%
\def\forest at nodewalk@historyforward{0,}%
- \ifforestdebugnodewalks\forest at nodewalk@makestep at debug\fi
\forest at process@keylist at register{every step}%
\fi
}
@@ -3232,6 +4629,11 @@
\noexpand\typeout{\ifforest at nodewalk@fake fake \fi "\forest at nodewalk@currentstepname" step to node id=\forest at cn, content=\forestoption{content}}%
}\forest at marshal
}%
+\def\forest at nodewalk@makestep at invalidtolastvalid@debug{%
+ \edef\forest at marshal{%
+ \noexpand\typeout{\ifforest at nodewalk@fake fake \fi "\forest at nodewalk@currentstepname" step to invalid node, (fake) return to last valid id=\forest at cn, content=\forestoption{content}}%
+ }\forest at marshal
+}%
\def\forest at handlers@savecurrentpath{%
\edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}%
\let\forest at currentkey\pgfkeyscurrentkey
@@ -3336,6 +4738,8 @@
{\noexpand\forest at forstepwrapper{#1\ifnum\forest at nodewalkstephandler@nargs>0=\fi\forest at util@nargs{####}{\number\numexpr\forest at nodewalkstephandler@nargs}{0}}{####\number\numexpr\forest at nodewalkstephandler@nargs+1}},
}%
\fi\fi
+ % Uncomment this to collect a list of for-based spatial propagators
+ %\appto\bigbadforlist{[#1]}%
\fi
},
}
@@ -3345,7 +4749,7 @@
}},
}
\def\forest at forstepwrapper#1#2{\forest at forthis{\forest at nodewalk{#1}{#2}}}
-\def\forest at util@nargs#1#2#3{% #1 = prefix (#, ##, ...), #2 = n args, #3=start; returns {#start}{#start+1}...{#start+n}
+\def\forest at util@nargs#1#2#3{% #1 = prefix (#, ##, ...), #2 = n args, #3=start; returns {#start+1}...{#start+n}
\ifnum#2>0 {#1\number\numexpr#3+1}\fi
\ifnum#2>1 {#1\number\numexpr#3+2}\fi
\ifnum#2>2 {#1\number\numexpr#3+3}\fi
@@ -3357,7 +4761,11 @@
\ifnum#2>8 {#1\number\numexpr#3+9}\fi
}
\def\forest at nodewalk@start at oninvalid@fake#1{}
-\def\forest at nodewalk@start at oninvalid@real#1{}
+\def\forest at nodewalk@start at oninvalid@compatfake#1{%
+ \forest at deprecated{last step in stack "\forest at nodewalk@currentstepname", which started from an invalid node; enabled by "compat=1.0-forstep". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}%
+}%
+\let\forest at nodewalk@start at oninvalid@errorifreal\forest at nodewalk@start at oninvalid@fake % the step will be to an invalid node anyway
+\let\forest at nodewalk@start at oninvalid@lastvalid\forest at nodewalk@start at oninvalid@fake
\def\forest at nodewalk@start at oninvalid@error#1{\PackageError{forest}{nodewalk step "#1" cannot start at the invalid node}{}}
\forestset{
define long step={current}{autostep}{},
@@ -3403,7 +4811,7 @@
},
define long step={next leaf}{style,strip fake steps=false}{group={do until={n_children()==0}{next node}}},
define long step={previous leaf}{style,strip fake steps=false}{group={do until={n_children()==0}{previous node}}},
- define long step={next on tier}{autostep}{%
+ define long step={next on tier}{autostep,n args=1}{%
\def\forest at temp{#1}%
\ifx\forest at temp\pgfkeysnovalue at text
\forestoget{tier}\forest at nodewalk@giventier
@@ -3410,14 +4818,14 @@
\else
\def\forest at nodewalk@giventier{#1}%
\fi
- \edef\forest at cn{\forest at node@linearnextnotdescendantid}%
+ \edef\forest at cn{\forest at node@linearnextid}%
\safeloop
- \forestoget{tier}\forest at nodewalk@tier
- \unless\ifx\forest at nodewalk@tier\forest at nodewalk@giventier
+ \forest at nodewalk@gettier
+ \ifforest at temp
\edef\forest at cn{\forest at node@linearnextid}%
\saferepeat
},
- define long step={previous on tier}{autostep}{%
+ define long step={previous on tier}{autostep,n args=1}{%
\def\forest at temp{#1}%
\ifx\forest at temp\pgfkeysnovalue at text
\forestoget{tier}\forest at nodewalk@giventier
@@ -3426,10 +4834,24 @@
\fi
\safeloop
\edef\forest at cn{\forest at node@linearpreviousid}%
- \forestoget{tier}\forest at nodewalk@tier
- \unless\ifx\forest at nodewalk@tier\forest at nodewalk@giventier
+ \forest at nodewalk@gettier
+ \ifforest at temp
\saferepeat
},
+ TeX={%
+ \def\forest at nodewalk@gettier{%
+ \ifnum\forest at cn=0
+ \forest at tempfalse
+ \else
+ \forestoget{tier}\forest at temp
+ \ifx\forest at temp\forest at nodewalk@giventier
+ \forest at tempfalse
+ \else
+ \forest at temptrue
+ \fi
+ \fi
+ }%
+ },
%
define long step={root}{autostep,must start at valid node=false}{%
\edef\forest at cn{\forest at node@rootid}},
@@ -3439,7 +4861,7 @@
define long step={origin}{autostep,must start at valid node=false}{\edef\forest at cn{\forest at nodewalk@origin}},
%
define long step={n}{autostep,n args=1}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\edef\forest at cn{\forest at node@nthchildid{\forest at temp@n}}%
},
define long step={n}{autostep,make for=false,n args=1}{%
@@ -3449,19 +4871,19 @@
\ifx\forest at nodewalk@temp\pgfkeysnovalue at text
\edef\forest at cn{\forestove{@next}}%
\else
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\edef\forest at cn{\forest at node@nthchildid{\forest at temp@n}}%
\fi
},
define long step={n'}{autostep,n args=1}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\edef\forest at cn{\forest at node@nbarthchildid{\forest at temp@n}}%
},
define long step={to tier}{autostep,n args=1}{%
\def\forest at nodewalk@giventier{#1}%
\safeloop
- \forestoget{tier}\forest at nodewalk@tier
- \unless\ifx\forest at nodewalk@tier\forest at nodewalk@giventier
+ \forest at nodewalk@gettier
+ \ifforest at temp
\forestoget{@parent}\forest at cn
\saferepeat
},
@@ -3478,45 +4900,35 @@
\def\forest at nodewalk@config at everystep@method{independent}%
\def\forest at nodewalk@config at history@method{shared}%
\def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \pgfqkeys{/forest/nodewalk at config}{#1}%
- \forest at Nodewalk{#2}{#3}%
- }%
+ \pgfqkeys{/forest/nodewalk at config}{#1}%
+ \forest at Nodewalk{#2}{#3}%
},
define long step={nodewalk}{n args=2, at bare}{% #1 = nodewalk, #2 = every step
\forest at nodewalk{#1}{#2}%
},
- define long step={nodewalk'}{n args=1, at bare}{% #1 = nodewalk, #2 = every step
- \def\forest at nodewalk@config at everystep@method{inherited}%
- \def\forest at nodewalk@config at history@method{independent}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at Nodewalk{#1}{}%
- }%
+ define long step={nodewalk'}{n args=1, at bare}{% #1 = nodewalk
+ \forest at configured@nodewalk{inherited}{independent}{inherited}{#1}{}%
},
- % these must be defined explicitely, as prefix "for" normally introduces the every-step keylist
- for nodewalk/.code 2 args={%
+ % these "for ..." keys must be defined explicitely
+ % (and copied into node keyspace manually),
+ % as prefix "for" normally introduces the every-step keylist
+ define long step={for nodewalk}{n args=2, at bare}{% #1 = nodewalk, #2 = every step
\forest at forthis{\forest at nodewalk{#1}{#2}}},
- for nodewalk'/.code={%
- \def\forest at nodewalk@config at everystep@method{inherited}%
- \def\forest at nodewalk@config at history@method{independent}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at forthis{\forest at Nodewalk{#1}{}}%
+ define long step={for nodewalk'}{n args=1, at bare}{% #1 = nodewalk
+ \forest at forthis{%
+ \forest at configured@nodewalk{inherited}{independent}{inherited}{#1}{}%
}%
},
- for Nodewalk/.code n args=3{% #1 = config, #2 = nodewalk, #3 = every-step
- \def\forest at nodewalk@config at everystep@method{inherited}%
- \def\forest at nodewalk@config at history@method{independent}%
+ define long step={for Nodewalk}{n args=3, at bare}{% #1 = config, #2 = nodewalk, #3 = every-step
+ \def\forest at nodewalk@config at everystep@method{independent}%
+ \def\forest at nodewalk@config at history@method{shared}%
\def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \pgfqkeys{/forest/nodewalk at config}{#1}%
- \forest at forthis{\forest at Nodewalk{#2}{#3}}%
- }%
+ \pgfqkeys{/forest/nodewalk at config}{#1}%
+ \forest at forthis{\forest at Nodewalk{#2}{#3}}%
},
- copy command key={/forest/for nodewalk}{/forest/nodewalk/for nodewalk},
- copy command key={/forest/for nodewalk'}{/forest/nodewalk/for nodewalk'},
- copy command key={/forest/for Nodewalk}{/forest/nodewalk/for Nodewalk},
+ copy command key={/forest/nodewalk/Nodewalk}{/forest/Nodewalk},
+ copy command key={/forest/nodewalk/for nodewalk}{/forest/for nodewalk},
+ copy command key={/forest/nodewalk/for Nodewalk}{/forest/for Nodewalk},
declare keylist register=every step,
every step'={},
%%% begin nodewalk config
@@ -3536,23 +4948,25 @@
on at invalid/.is choice,
on at invalid/error/.code={},
on at invalid/fake/.code={},
- on at invalid/step/.code={},
+ on at invalid/error if real/.code={},
+ on at invalid/last valid/.code={},
on at invalid/inherited/.code={},
on invalid/.store in=\forest at nodewalk@config at oninvalid,
on invalid/.prefix style={on at invalid=#1},
%%% end nodewalk config
}
+\newtoks\forest at nodewalk@branch at toks
\forestset{
declare toks register=branch at temp@toks,
branch at temp@toks={},
declare keylist register=branched at nodewalk,
branched at nodewalk={},
- define long step={branch}{n args=1, at bare,style}{@branch={#1}{branch at build@realstep,branch at build@fakestep}},
- define long step={branch'}{n args=1, at bare,style}{@branch={#1}{branch at build@realstep}},
+ define long step={branch}{n args=1, at bare,make for,style}{@branch={#1}{branch at build@realstep,branch at build@fakestep}},
+ define long step={branch'}{n args=1, at bare,make for,style}{@branch={#1}{branch at build@realstep}},
@branch/.style 2 args={%
save and restore register={branched at nodewalk}{
branch at temp@toks={},
- split/.process args={r}{#1}{,}{#2},
+ split/.process={r}{#1}{,}{#2},
branch at temp@style/.style/.register=branch at temp@toks,
branch at temp@style,
branch at temp@style/.style/.register=branched at nodewalk,
@@ -3568,7 +4982,7 @@
branch at temp@toks/.expanded={for nodewalk={\unexpanded{#1}}{
\forestregister{branch at temp@toks}}},
},
- define long step={group}{autostep}{\forest at go{#1}},
+ define long step={group}{autostep,n args=1}{\forest at go{#1}},
nodewalk/fake/.code={%
\forest at saveandrestoreifcs{forest at nodewalk@fake}{%
\forest at nodewalk@faketrue
@@ -3583,7 +4997,7 @@
},
declare keylist register=filtered at nodewalk,
filtered at nodewalk={},
- define long step={filter}{n args=2, at bare,style}{% #1 = nodewalk, #2 = condition
+ define long step={filter}{n args=2, at bare,make for,style}{% #1 = nodewalk, #2 = condition
save and restore register={filtered at nodewalk}{
filtered at nodewalk'={},
Nodewalk=%
@@ -3592,12 +5006,13 @@
{if={#2}{filtered at nodewalk+/.expanded={id=\forestoption{id}}}{}},
filtered at nodewalk@style/.style/.register=filtered at nodewalk,
filtered at nodewalk@style
- }
+ },
},
on at invalid/.is choice,
on at invalid/error/.code={},
on at invalid/fake/.code={},
- on at invalid/step/.code={},
+ on at invalid/error if real/.code={},
+ on at invalid/last valid/.code={},
on invalid/.code 2 args={%
\pgfkeysalso{/forest/on at invalid={#1}}%
\forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
@@ -3607,38 +5022,54 @@
},
define long step={strip fake steps}{n args=1, at bare}{%
\forest at nodewalk@stripfakesteps{\pgfkeysalso{#1}}},
+ define long step={unique}{n args=1}{%
+ \begingroup
+ \def\forest at nodewalk@unique at temp{}%
+ \forest at nodewalk{#1}{%
+ TeX={%
+ \forestoget{unique at visited}\forest at temp
+ \ifx\forest at temp\relax
+ \forestoset{unique at visited}{1}%
+ \eappto\forest at nodewalk@unique at temp{,id=\forest at cn}%
+ \fi
+ }%
+ }%
+ \global\let\forest at global@temp\forest at nodewalk@unique at temp
+ \endgroup
+ \pgfkeysalsofrom{\forest at global@temp}%
+ },
define long step={walk back}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyforward}{\forest at nodewalk@historyback}{\ifnum\forest at cn=0 0\else1\fi}{\forest at temp@n+\ifnum\forest at cn=0 0\else1\fi}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@back at updatehistory
},
nodewalk/walk back/.default=1,
define long step={jump back}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{(#1)+\ifnum\forest at cn=0 0\else1\fi}%
+ \forestmathtruncatemacro\forest at temp@n{(#1)+\ifnum\forest at cn=0 0\else1\fi}%
\forest at nodewalk@walklist{\forest at nodewalk@historyforward}{\forest at nodewalk@historyback}{\forest at temp@n-1}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@back at updatehistory
},
nodewalk/jump back/.default=1,
define long step={back}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyforward}{\forest at nodewalk@historyback}{\ifnum\forest at cn=0 0\else1\fi}{\forest at temp@n+\ifnum\forest at cn=0 0\else1\fi}{\let\forest at cn\forest at nodewalk@cn\forest at saveandrestoreifcs{forest at nodewalk@fake}{\forest at nodewalk@faketrue\forest at nodewalk@makestep}}%
\forest at nodewalk@back at updatehistory
},
nodewalk/back/.default=1,
define long step={walk forward}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyback}{\forest at nodewalk@historyforward}{0}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@forward at updatehistory
},
nodewalk/walk forward/.default=1,
define long step={jump forward}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyback}{\forest at nodewalk@historyforward}{\forest at temp@n-1}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at nodewalk@makestep}%
\forest at nodewalk@forward at updatehistory
},
nodewalk/jump forward/.default=1,
define long step={forward}{n args=1, at bare}{%
- \pgfmathtruncatemacro\forest at temp@n{#1}%
+ \forestmathtruncatemacro\forest at temp@n{#1}%
\forest at nodewalk@walklist{\forest at nodewalk@historyback}{\forest at nodewalk@historyforward}{0}{\forest at temp@n}{\let\forest at cn\forest at nodewalk@cn\forest at saveandrestoreifcs{forest at nodewalk@fake}{\forest at nodewalk@faketrue\forest at nodewalk@makestep}}%
\forest at nodewalk@forward at updatehistory
},
@@ -3691,7 +5122,9 @@
\noexpand\forest at nodewalk@sortlist{\noexpand\forest at nodewalk@historyback}{\noexpand\forest at nodewalk@n-\forest at nodewalk@n}\noexpand\forest at sort@descending
}\forest at marshal
},
- sort by/.store in=\forest at nodesort@by,
+ declare keylist register=sort by,
+ copy command key={/forest/sort by'}{/forest/sort by},
+ sort by={},
define long step={save}{n args=2, at bare,make for}{% #1 = name, #2 = nodewalk
\forest at forthis{%
\forest at nodewalk{#2,TeX={%
@@ -3709,6 +5142,21 @@
}\forest at marshal
\csedef{forest at nodewalk@saved@#1}{\forest at nodewalk@walklist at walked}%
},
+ define long step={save append}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{save}{\cseappto}},
+ define long step={save prepend}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{save}{\csepreto}},
+ define long step={walk and save append}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{walk and save}{\cseappto}},
+ define long step={walk and save prepend}{style,n args=2, at bare,make for}{% #1 = nodewalk name, #2 = nodewalk
+ save at append@prepend={#1}{#2}{walk and save}{\csepreto}},
+ nodewalk/save at append@prepend/.code n args=4{%
+ % #1 = nodewalk name, #2 = nodewalk
+ % #3 = "(walk and) save" #4 = \cseappto/\csepreto
+ \pgfkeysalso{#3={@temp}{#2}}%
+ \letcs\forest at temp{forest at nodewalk@saved@@temp}%
+ #4{forest at nodewalk@saved@#1}{\expandonce{\forest at temp}}%
+ },
nodewalk/save history/.code 2 args={% #1 = back, forward
\csedef{forest at nodewalk@saved@#1}{\forest at nodewalk@historyback}%
\csedef{forest at nodewalk@saved@#2}{\forest at nodewalk@historyforward}%
@@ -3799,12 +5247,7 @@
\let\forest at nodewalk@historyback\forest at nodewalk@walklist at walked
}
\def\forest at go#1{%
- \def\forest at nodewalk@config at everystep@method{independent}%
- \def\forest at nodewalk@config at history@method{inherited}%
- \def\forest at nodewalk@config at oninvalid{inherited}%
- \forest at saveandrestoremacro\forest at nodewalk@oninvalid{%
- \forest at Nodewalk{#1}{}%
- }%
+ \forest at configured@nodewalk{independent}{inherited}{inherited}{#1}{}%
}
\def\forest at csvlist@getfirst@#1{% assuming that the list is nonempty and finishes with a comma
\forest at csvlist@getfirst@@#1\forest at csvlist@getfirst@@}
@@ -3852,7 +5295,7 @@
\expandafter\forest at csvlist@getfirstrest@\expandafter{\forest at nodewalksort@list}\forest at nodewalksort@cn\forest at nodewalksort@list
\csedef{forest at nodesort@\safeloopn}{\forest at nodewalksort@cn}%
\saferepeat
- \edef\forest at nodesort@sortkey{\forest at nodesort@by}%
+ \forestrget{sort by}\forest at nodesort@sortkey
\forest at sort\forest at nodesort@cmpnodes\forest at nodesort@let#2{1}{#1}%
\def\forest at nodewalksort@sorted{}%
\safeloop
@@ -3936,7 +5379,7 @@
% #2 = max index in list (start with 1)
% #3 = min/max = ascending/descending = </>
% #4 = how many results? 1 = {\forest at nodewalk@minmax at node,}, all={\forest at nodewalk@minmax at nodes}, walk in history={}
- \edef\forest at nodesort@sortkey{\forest at nodesort@by}%
+ \forestrget{sort by}\forest at nodesort@sortkey
\edef\forest at nodewalk@minmax at N{\number\numexpr#2}%
\edef\forest at nodewalk@minmax at n{}%
\edef\forest at nodewalk@minmax at list{#1}%
@@ -4146,7 +5589,7 @@
define long step={descendants breadth-first}{}{\forest at node@foreach at breadthfirst{0}{\forest at nodewalk@makestep}},
define long step={descendants breadth-first reversed}{}{\forest at node@foreach at breadthfirst@reversed{0}{\forest at nodewalk@makestep}},
define long step={level}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{\forest at temp}%
@@ -4154,7 +5597,7 @@
}\forest at marshal
},
define long step={level>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{-1}%
@@ -4162,8 +5605,7 @@
}\forest at marshal
},
define long step={level<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)-1}%
- \show\forest at temp
+ \forestmathtruncatemacro\forest at temp{(#1)-1}%
\ifnum\forest at temp=-1
% special case, as \forest at node@foreach at breadthfirst uses level<0 as a signal for unlimited max level
\ifnum\forestove{level}=0
@@ -4178,7 +5620,7 @@
\fi
},
define long step={level reversed}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4186,7 +5628,7 @@
}\forest at marshal
},
define long step={level reversed>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{#1}%
+ \forestmathtruncatemacro\forest at temp{#1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{-1}%
@@ -4194,7 +5636,7 @@
}\forest at marshal
},
define long step={level reversed<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)-1}%
+ \forestmathtruncatemacro\forest at temp{(#1)-1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4203,7 +5645,7 @@
},
%
define long step={relative level}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{\forest at temp}%
@@ -4211,7 +5653,7 @@
}\forest at marshal
},
define long step={relative level>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{-1}%
@@ -4219,7 +5661,7 @@
}\forest at marshal
},
define long step={relative level<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst
{\forest at temp}%
@@ -4227,7 +5669,7 @@
}\forest at marshal
},
define long step={relative level reversed}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4235,7 +5677,7 @@
}\forest at marshal
},
define long step={relative level reversed>}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{-1}%
@@ -4243,7 +5685,7 @@
}\forest at marshal
},
define long step={relative level reversed<}{n args=1}{%
- \pgfmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
+ \forestmathtruncatemacro\forest at temp{(#1)+\forestove{level}-1}%
\edef\forest at marshal{%
\noexpand\forest at node@foreach at breadthfirst@reversed
{\forest at temp}%
@@ -4250,6 +5692,19 @@
{\noexpand\forest at nodewalk@makestep}%
}\forest at marshal
},
+ define long step={leaves}{}{%
+ \forest at node@foreach{%
+ \ifnum\forestove{n children}=0
+ \forest at nodewalk@makestep
+ \fi
+ }%
+ },
+ define long step={-level}{n args=1,style}{%
+ unique={branch={leaves,{group={repeat={#1}{parent}}}}}
+ },
+ define long step={-level'}{n args=1,style}{%
+ unique={on invalid={fake}{branch={leaves,{group={repeat={#1}{parent}}}}}}
+ },
define long step={children}{}{\forest at node@foreachchild{\forest at nodewalk@makestep}},
define long step={children reversed}{}{\forest at node@foreachchild at reversed{\forest at nodewalk@makestep}},
define long step={current and following siblings}{}{\forest at node@@forselfandfollowingsiblings{\forest at nodewalk@makestep}},
@@ -4327,9 +5782,15 @@
\def\forest at saveandrestoreifcs#1#2{% #1 = the if cs to save before and restore after processing code in #2
\edef\forest at marshal{%
\unexpanded{#2}%
- \ifbool{#1}{\noexpand\setbool{#1}{true}}{\noexpand\setbool{#1}{false}}
+ \ifbool{#1}{\noexpand\setbool{#1}{true}}{\noexpand\setbool{#1}{false}}%
}\forest at marshal
}
+\def\forest at globalsaveandrestoreifcs#1#2{% #1 = the if cs to save before and restore after processing code in #2
+ \edef\forest at marshal{%
+ \unexpanded{#2}%
+ \ifbool{#1}{\global\noexpand\setbool{#1}{true}}{\global\noexpand\setbool{#1}{false}}%
+ }\forest at marshal
+}
\def\forest at saveandrestoretoks#1#2{% #1 = the toks to save before and restore after processing code in #2
\edef\forest at marshal{%
\unexpanded{#2}%
@@ -4344,7 +5805,7 @@
}
\forestset{
save and restore register/.code 2 args={%
- \forest at saveandrestoreregister{filter at ed}{%
+ \forest at saveandrestoreregister{#1}{%
\pgfkeysalso{#2}%
}%
},
@@ -4455,21 +5916,16 @@
replace by''/.code={\forest at replaceby@code{#1}{insert after''}},
sort/.code={%
\eapptotoks\forest at do@dynamics{%
- \noexpand\forest at nodesort
- \noexpand\forest at sort@ascending
- {\forest at cn}%
- {\expandonce{\forest at nodesort@by}}%
+ \def\noexpand\forest at nodesort@sortkey{\forestrv{sort by}}%
+ \noexpand\forest at nodesort\noexpand\forest at sort@ascending{\forest at cn}
}%
},
sort'/.code={%
\eapptotoks\forest at do@dynamics{%
- \noexpand\forest at nodesort
- \noexpand\forest at sort@descending
- {\forest at cn}%
- {\expandonce{\forest at nodesort@by}}%
+ \def\noexpand\forest at nodesort@sortkey{\forestrv{sort by}}%
+ \noexpand\forest at nodesort\noexpand\forest at sort@descending{\forest at cn}
}%
},
- sort by/.store in=\forest at nodesort@by,
}
\def\forest at replaceby@code#1#2{%#1=node spec,#2=insert after['][']
\ifnum\forestove{@parent}=0
@@ -4485,10 +5941,9 @@
}%
\fi
}
-\def\forest at nodesort#1#2#3{% #1 = direction, #2 = parent node, #3 = sort key
+\def\forest at nodesort#1#2{% #1 = direction, #2 = parent node
\ifforestdebugdynamics\forestdebug at dynamics{before sorting children of #2}\fi
- \def\forest at nodesort@sortkey{#3}%
- \forest at fornode{#2}{\forest at nodesort@#1}%
+ \forest at fornode{#2}{\forest at nodesort@#1}%
\ifforestdebugdynamics\forestdebug at dynamics{after sorting children of #2}\fi
}
\def\forest at nodesort@#1{%
@@ -4516,29 +5971,53 @@
\forest at loop
\ifnum\c at pgf@counta<\forest at nodesort@n\relax
\advance\c at pgf@counta 1
- \edef\temp{\csname forest at nodesort@\the\c at pgf@counta\endcsname}%
\forest at node@append{\csname forest at nodesort@\the\c at pgf@counta\endcsname}%
\forest at repeat
}
\def\forest at nodesort@cmpnodes#1#2{%
- \global\let\forest at nodesort@cmpresult\forest at sort@cmp at eq
- \foreach \forest at temp@pgfmath in \forest at nodesort@sortkey {%
- \forest at fornode{\csname forest at nodesort@#1\endcsname}{%
- \pgfmathparse{\forest at temp@pgfmath}\global\let\forest at global@tempa\pgfmathresult}%
- \forest at fornode{\csname forest at nodesort@#2\endcsname}{%
- \pgfmathparse{\forest at temp@pgfmath}\global\let\forest at global@tempb\pgfmathresult}%
- \ifdim\forest at global@tempa pt<\forest at global@tempb pt
- \global\let\forest at nodesort@cmpresult\forest at sort@cmp at lt
- \breakforeach
- \else
- \ifdim\forest at global@tempa pt>\forest at global@tempb pt
- \global\let\forest at nodesort@cmpresult\forest at sort@cmp at gt
- \breakforeach
- \fi
+ \expandafter\forest at nodesort@cmpnodes@\forest at nodesort@sortkey,\forest at END{#1}{#2}%
+}
+\def\forest at nodesort@cmpnodes@#1,#2\forest at END#3#4{%
+ % #1=process ins+arg for this dimension, #2=for next dimensions
+ % #3, #4 = node ids
+ {%
+ \forest at fornode{\csname forest at nodesort@#3\endcsname}{%
+ \forestmathsetmacro\forest at nodesort@resulta{#1}%
+ }%
+ \forest at fornode{\csname forest at nodesort@#4\endcsname}{%
+ \forestmathsetmacro\forest at nodesort@resultb{#1}%
+ }%
+ \ifx\forestmathresulttype\forestmathtype at generic
+ \forest at cmp@error{\forest at nodesort@resulta}{\forest at nodesort@resultb}%
\fi
+ \edef\forest at temp{%
+ \noexpand\forest at nodesort@cmp
+ {\expandonce{\forest at nodesort@resulta}}%
+ {\expandonce{\forest at nodesort@resultb}}%
+ }%
+ \xdef\forest at global@temp{\forest at temp}%
}%
- \forest at nodesort@cmpresult
+ \if=\forest at global@temp
+ \let\forest at next\forest at nodesort@cmpnodes@
+ \else
+ \let\forest at next\forest at nodesort@cmpnodes at finish
+ \fi
+ \ifstrempty{#2}{\let\forest at next\forest at nodesort@cmpnodes at finish}{}%
+ \forest at next#2\forest at END{#3}{#4}%
}
+\def\forest at nodesort@cmpnodes at finish#1\forest at END#2#3{%
+ \let\forest at sort@cmp at result\forest at global@temp
+}
+\def\forest at nodesort@cmp{\csname fRsT at nsc@\forestmathresulttype\endcsname}
+\def\fRsT at nsc@#1{\csname fRsT at nsc@#1\endcsname}
+\def\fRsT at nsc@n#1#2{\ifnum#1<#2 <\else\ifnum#1=#2 =\else>\fi\fi}
+\def\fRsT at nsc@d#1#2{\ifdim#1<#2 <\else\ifdim#1=#2 =\else>\fi\fi}
+\def\fRsT at nsc@P#1#2{\ifdim#1pt<#2pt <\else\ifdim#1pt=#2pt =\else>\fi\fi}
+\def\fRsT at nsc@t#1#2{\csname fRsT at nsc@\pdfstrcmp{#1}{#2}\endcsname}
+\def\fRsT at nsc@T#1#2{\csname fRsT at nsc@\pdfstrcmp{#2}{#1}\endcsname}
+\csdef{fRsT at nsc@-1}{<}
+\csdef{fRsT at nsc@0}{=}
+\csdef{fRsT at nsc@1}{>}
\def\forest at nodesort@let#1#2{%
\csletcs{forest at nodesort@#1}{forest at nodesort@#2}%
}
@@ -4596,10 +6075,17 @@
declare keylist={before computing xy}{},
declare keylist={before drawing tree}{},
declare keylist={delay}{},
- delay n/.style 2 args={if={#1==0}{#2}{delay at n={#1}{#2}}},
- delay at n/.style 2 args={
- if={#1==1}{delay={#2}}{delay={delay at n/.process args={P}{#1-1}{#2}}}
+ delay n/.code 2 args={%
+ \forestmathsetcount\forest at temp@count{#1}%
+ \pgfkeysalso{delay n'={\forest at temp@count}{#2}}%
},
+ delay n'/.code 2 args={
+ \ifnum#1=0
+ \pgfkeysalso{#2}%
+ \else
+ \pgfkeysalso{delay={delay n'/.expand once=\expandafter{\number\numexpr#1-1\relax}{#2}}}%
+ \fi
+ },
if have delayed/.style 2 args={if have delayed'={processing order}{#1}{#2}},
if have delayed'/.code n args=3{%
\forest at havedelayedoptionsfalse
@@ -5076,7 +6562,7 @@
\def\forest at pack@pgfpoint at childsposition#1{%
{%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\forest at fornode{#1}{%
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}%
}%
@@ -5085,7 +6571,7 @@
\def\forest at pack@pgfpoint at positioningrow#1{%
{%
\pgftransformreset
- \pgftransformrotate{#1}%
+ \forest at pgfqtransformrotate{#1}%
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}%
}%
}
@@ -5102,7 +6588,7 @@
{%
\edef\forest at temp@child{\forest at node@nornbarthchildid{\forestove{calign primary child}}}%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\pgfpointtransformed{\pgfqpoint{\forestOve{\forest at temp@child}{l}}{\forestOve{\forest at temp@child}{s}}}%
\pgf at xa=\pgf at x\relax\pgf at ya=\pgf at y\relax
\forest at Pointanchor{\forest at temp@child}{child anchor}%
@@ -5111,7 +6597,7 @@
\advance\pgf at xa-\pgf at x\relax\advance\pgf at ya-\pgf at y\relax
\edef\forest at marshal{%
\noexpand\pgftransformreset
- \noexpand\pgftransformrotate{-\forestove{grow}}%
+ \noexpand\forest at pgfqtransformrotate{-\forestove{grow}}%
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf at xa}{\the\pgf at ya}}%
}\forest at marshal
}%
@@ -5129,7 +6615,7 @@
\edef\forest at temp@firstchild{\forest at node@nornbarthchildid{\forestove{calign primary child}}}%
\edef\forest at temp@secondchild{\forest at node@nornbarthchildid{\forestove{calign secondary child}}}%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\pgfpointtransformed{\pgfqpoint{\forestOve{\forest at temp@firstchild}{l}}{\forestOve{\forest at temp@firstchild}{s}}}%
\pgf at xa=\pgf at x\relax\pgf at ya=\pgf at y\relax
\forest at Pointanchor{\forest at temp@firstchild}{child anchor}%
@@ -5145,12 +6631,16 @@
\advance\pgf at xa-\pgf at x\relax\advance\pgf at ya-\pgf at y\relax
\edef\forest at marshal{%
\noexpand\pgftransformreset
- \noexpand\pgftransformrotate{-\forestove{grow}}%
+ \noexpand\forest at pgfqtransformrotate{-\forestove{grow}}%
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf at xa}{\the\pgf at ya}}%
}\forest at marshal
}%
\forest at calign@s at shift{\the\dimexpr-\the\pgf at y}%
}
+\def\forest at edef@strippt#1#2{%
+ \edef#1{#2}%
+ \edef#1{\expandafter\Pgf at geT#1}%
+}
\csdef{forest at calign@fixed angles}{%
\ifnum\forestove{n children}>1
\edef\forest at ca@first at child{\forest at node@nornbarthchildid{\forestove{calign primary child}}}%
@@ -5161,19 +6651,35 @@
\let\forest at ca@second at child\forest at temp
\fi
\forestOget{\forest at ca@first at child}{l}\forest at ca@first at l
+ \edef\forest at ca@first at l{\expandafter\Pgf at geT\forest at ca@first at l}%
\forestOget{\forest at ca@second at child}{l}\forest at ca@second at l
- \pgfmathsetlengthmacro\forest at ca@desired at s@distance{%
- tan(\forestove{calign secondary angle})*\forest at ca@second at l
- -tan(\forestove{calign primary angle})*\forest at ca@first at l
- }%
+ \edef\forest at ca@second at l{\expandafter\Pgf at geT\forest at ca@second at l}%
+ \pgfmathtan@{\forestove{calign secondary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@second at l}%
+ \let\forest at calign@temp\pgfmathresult
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@first at l}%
+ \edef\forest at ca@desired at s@distance{\the\dimexpr
+ \forest at calign@temp pt-\pgfmathresult pt}%
+ % \pgfmathsetlengthmacro\forest at ca@desired at s@distance{%
+ % tan(\forestove{calign secondary angle})*\forest at ca@second at l
+ % -tan(\forestove{calign primary angle})*\forest at ca@first at l
+ % }%
\forestOget{\forest at ca@first at child}{s}\forest at ca@first at s
\forestOget{\forest at ca@second at child}{s}\forest at ca@second at s
- \pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ \edef\forest at ca@actual at s@distance{\the\dimexpr
\forest at ca@second at s-\forest at ca@first at s}%
+ %\pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ % \forest at ca@second at s-\forest at ca@first at s}%
\ifdim\forest at ca@desired at s@distance>\forest at ca@actual at s@distance\relax
\ifdim\forest at ca@actual at s@distance=0pt
- \pgfmathsetlength\pgfutil at tempdima{tan(\forestove{calign primary angle})*\forest at ca@second at l}%
- \pgfmathsetlength\pgfutil at tempdimb{\forest at ca@desired at s@distance/(\forestove{n children}-1)}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@second at l}%
+ \pgfutil at tempdima=\pgfmathresult pt
+ % \pgfmathsetlength\pgfutil at tempdima{tan(\forestove{calign primary angle})*\forest at ca@second at l}%
+ \pgfutil at tempdimb=\dimexpr
+ \forest at ca@desired at s@distance/(\forestove{n children}-1)\relax%
+ %\pgfmathsetlength\pgfutil at tempdimb{\forest at ca@desired at s@distance/(\forestove{n children}-1)}%
\forest at node@foreachchild{%
\forestoeset{s}{\the\pgfutil at tempdima}%
\advance\pgfutil at tempdima\pgfutil at tempdimb
@@ -5180,26 +6686,49 @@
}%
\def\forest at calign@anchor{0pt}%
\else
- \pgfmathsetmacro\forest at ca@ratio{%
- \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetmacro\forest at ca@ratio{%
+ % \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
\forest at node@foreachchild{%
- \pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{s}}%
- \forestolet{s}\forest at temp
+ \forest at edef@strippt\forest at temp{\forestove{s}}%
+ \pgfmathmultiply@{\forest at ca@ratio}{\forest at temp}%
+ \forestoeset{s}{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{s}}%
+ %\forestolet{s}\forest at temp
}%
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@first at l}%
+ \edef\forest at calign@anchor{\the\dimexpr-\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
\fi
\else
\ifdim\forest at ca@desired at s@distance<\forest at ca@actual at s@distance\relax
- \pgfmathsetlengthmacro\forest at ca@ratio{%
- \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetlengthmacro\forest at ca@ratio{%
+ % \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
\forest at node@foreachchild{%
- \pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{l}}%
- \forestolet{l}\forest at temp
+ \forest at edef@strippt\forest at temp{\forestove{l}}%
+ \pgfmathmultiply@{\forest at ca@ratio}{\forest at temp}%
+ \forestoeset{l}{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at temp{\forest at ca@ratio*\forestove{l}}%
+ %\forestolet{l}\forest at temp
}%
\forestOget{\forest at ca@first at child}{l}\forest at ca@first at l
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
+ \edef\forest at ca@first at l{\expandafter\Pgf at geT\forest at ca@first at l}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \pgfmathmultiply@{\pgfmathresult}{\forest at ca@first at l}%
+ \edef\forest at calign@anchor{\the\dimexpr-\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*\forest at ca@first at l}%
\fi
\fi
\forest at calign@s at shift{-\forest at calign@anchor}%
@@ -5225,16 +6754,33 @@
\forest at Pointanchor{\forest at ca@second at child}{child anchor}%
\edef\forest at ca@second at child@anchor at s{\the\pgf at x}%
\edef\forest at ca@second at child@anchor at l{\the\pgf at y}%
- \pgfmathsetlengthmacro\forest at ca@desired at second@edge at s{tan(\forestove{calign secondary angle})*%
- (\forest at ca@second at l-\forest at ca@second at child@anchor at l+\forest at ca@parent at anchor@l)}%
- \pgfmathsetlengthmacro\forest at ca@desired at first@edge at s{tan(\forestove{calign primary angle})*%
- (\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)}
- \pgfmathsetlengthmacro\forest at ca@desired at s@distance{\forest at ca@desired at second@edge at s-\forest at ca@desired at first@edge at s}%
+ \pgfmathtan@{\forestove{calign secondary angle}}%
+ \edef\forest at temp{\the\dimexpr
+ \forest at ca@second at l-\forest at ca@second at child@anchor at l+\forest at ca@parent at anchor@l}%
+ \pgfmathmultiply@{\pgfmathresult}{\expandafter\Pgf at geT\forest at temp}%
+ \edef\forest at ca@desired at second@edge at s{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at ca@desired at second@edge at s{%
+ % tan(\forestove{calign secondary angle})*%
+ % (\forest at ca@second at l-\forest at ca@second at child@anchor at l+\forest at ca@parent at anchor@l)}%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \edef\forest at temp{\the\dimexpr
+ \forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l}%
+ \pgfmathmultiply@{\pgfmathresult}{\expandafter\Pgf at geT\forest at temp}%
+ \edef\forest at ca@desired at first@edge at s{\the\dimexpr\pgfmathresult pt}%
+ %\pgfmathsetlengthmacro\forest at ca@desired at first@edge at s{%
+ % tan(\forestove{calign primary angle})*%
+ % (\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)}%
+ \edef\forest at ca@desired at s@distance{\the\dimexpr
+ \forest at ca@desired at second@edge at s-\forest at ca@desired at first@edge at s}%
+ %\pgfmathsetlengthmacro\forest at ca@desired at s@distance{\forest at ca@desired at second@edge at s-\forest at ca@desired at first@edge at s}%
\forestOget{\forest at ca@first at child}{s}\forest at ca@first at s
\forestOget{\forest at ca@second at child}{s}\forest at ca@second at s
- \pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ \edef\forest at ca@actual at s@distance{\the\dimexpr
\forest at ca@second at s+\forest at ca@second at child@anchor at s
-\forest at ca@first at s-\forest at ca@first at child@anchor at s}%
+ %\pgfmathsetlengthmacro\forest at ca@actual at s@distance{%
+ % \forest at ca@second at s+\forest at ca@second at child@anchor at s
+ % -\forest at ca@first at s-\forest at ca@first at child@anchor at s}%
\ifdim\forest at ca@desired at s@distance>\forest at ca@actual at s@distance\relax
\ifdim\forest at ca@actual at s@distance=0pt
\forestoget{n children}\forest at temp@n at children
@@ -5241,48 +6787,90 @@
\forest at node@foreachchild{%
\forest at pointanchor{child anchor}%
\edef\forest at temp@child at anchor@s{\the\pgf at x}%
- \pgfmathsetlengthmacro\forest at temp{%
- \forest at ca@desired at first@edge at s+(\forestove{n}-1)*\forest at ca@desired at s@distance/(\forest at temp@n at children-1)+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
- \forestolet{s}\forest at temp
+ \forestoeset{s}{\the\dimexpr
+ \forest at ca@desired at first@edge at s+\forest at ca@desired at s@distance*(\forestove{n}-1)/(\forest at temp@n at children-1)+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
+ %\pgfmathsetlengthmacro\forest at temp{%
+ % \forest at ca@desired at first@edge at s+(\forestove{n}-1)*\forest at ca@desired at s@distance/(\forest at temp@n at children-1)+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
+ %\forestolet{s}\forest at temp
}%
\def\forest at calign@anchor{0pt}%
\else
- \pgfmathsetmacro\forest at ca@ratio{%
- \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetmacro\forest at ca@ratio{%
+ % \forest at ca@desired at s@distance/\forest at ca@actual at s@distance}%
\forest at node@foreachchild{%
\forest at pointanchor{child anchor}%
\edef\forest at temp@child at anchor@s{\the\pgf at x}%
- \pgfmathsetlengthmacro\forest at temp{%
- \forest at ca@ratio*(%
- \forestove{s}-\forest at ca@first at s
- +\forest at temp@child at anchor@s-\forest at ca@first at child@anchor at s)%
- +\forest at ca@first at s
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\forest at ca@ratio}%
+ {\expandafter\Pgf at geT\the\dimexpr
+ \forestove{s}-\forest at ca@first at s+%
+ \forest at temp@child at anchor@s-\forest at ca@first at child@anchor at s}%
+ }\forest at marshal
+ \forestoeset{s}{\the\dimexpr\pgfmathresult pt+\forest at ca@first at s
+\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
- \forestolet{s}\forest at temp
+ % \pgfmathsetlengthmacro\forest at temp{%
+ % \forest at ca@ratio*(%
+ % \forestove{s}-\forest at ca@first at s
+ % +\forest at temp@child at anchor@s-\forest at ca@first at child@anchor at s)%
+ % +\forest at ca@first at s
+ % +\forest at ca@first at child@anchor at s-\forest at temp@child at anchor@s}%
+ % \forestolet{s}\forest at temp
}%
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*(\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)%
- +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
- }%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\pgfmathresult}%
+ {\expandafter\Pgf at geT\the\dimexpr
+ \forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l}%
+ }\forest at marshal
+ \edef\forest at calign@anchor{\the\dimexpr
+ -\pgfmathresult pt+\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s}%
+ % \pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*(\forest at ca@first at l-\forest at ca@first at child@anchor at l+\forest at ca@parent at anchor@l)%
+ % +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
+ % }%
\fi
\else
\ifdim\forest at ca@desired at s@distance<\forest at ca@actual at s@distance\relax
- \pgfmathsetlengthmacro\forest at ca@ratio{%
- \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
+ \edef\forest at marshal{\noexpand\pgfmathdivide@
+ {\expandafter\Pgf at geT\forest at ca@actual at s@distance}%
+ {\expandafter\Pgf at geT\forest at ca@desired at s@distance}%
+ }\forest at marshal
+ \let\forest at ca@ratio\pgfmathresult
+ %\pgfmathsetlengthmacro\forest at ca@ratio{%
+ % \forest at ca@actual at s@distance/\forest at ca@desired at s@distance}%
\forest at node@foreachchild{%
\forest at pointanchor{child anchor}%
\edef\forest at temp@child at anchor@l{\the\pgf at y}%
- \pgfmathsetlengthmacro\forest at temp{%
- \forest at ca@ratio*(%
- \forestove{l}+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)
- -\forest at ca@parent at anchor@l+\forest at temp@child at anchor@l}%
- \forestolet{l}\forest at temp
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\forest at ca@ratio}%
+ {\expandafter\Pgf at geT\the\dimexpr\forestove{l}+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l}%
+ }\forest at marshal
+ \forestoeset{l}{\the\dimexpr
+ \pgfmathresult pt-\forest at ca@parent at anchor@l+\forest at temp@child at anchor@l}%
+ % \pgfmathsetlengthmacro\forest at temp{%
+ % \forest at ca@ratio*(%
+ % \forestove{l}+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)
+ % -\forest at ca@parent at anchor@l+\forest at temp@child at anchor@l}%
+ % \forestolet{l}\forest at temp
}%
\forestOget{\forest at ca@first at child}{l}\forest at ca@first at l
- \pgfmathsetlengthmacro\forest at calign@anchor{%
- -tan(\forestove{calign primary angle})*(\forest at ca@first at l+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)%
- +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
- }%
+ \pgfmathtan@{\forestove{calign primary angle}}%
+ \edef\forest at marshal{\noexpand\pgfmathmultiply@
+ {\pgfmathresult}%
+ {\expandafter\Pgf at geT\the\dimexpr
+ \forest at ca@first at l+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l}%
+ }\forest at marshal
+ \edef\forest at calign@anchor{\the\dimexpr
+ -\pgfmathresult pt+\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s}%
+ % \pgfmathsetlengthmacro\forest at calign@anchor{%
+ % -tan(\forestove{calign primary angle})*(\forest at ca@first at l+\forest at ca@parent at anchor@l-\forest at temp@child at anchor@l)%
+ % +\forest at ca@first at child@anchor at s-\forest at ca@parent at anchor@s
+ % }%
\fi
\fi
\forest at calign@s at shift{-\forest at calign@anchor}%
@@ -5323,7 +6911,7 @@
\eappto\forest at node@edge{\noexpand\pgfsyssoftpath at movetotoken{\forest at getedge@pa at l}{\forest at getedge@pa at s}}%
\pgfgettransform\forest at temp@transform
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
\def\forest at all@edges{}%
\forest at node@foreachchild{%
\forestoget{#1 at edge@#2}\forest at temp@edge
@@ -5897,8 +7485,12 @@
}\forest at marshal
}
\def\forest at node@computeabsolutepositions@#1#2#3{%
- \pgfpointadd{\pgfpoint{#1}{#2}}{%
- \pgfpointadd{\pgfpolar{#3}{\forestove{l}}}{\pgfpolar{90 + #3}{\forestove{s}}}}%
+ \pgfpointadd
+ {\pgfqpoint{#1}{#2}}%
+ {\pgfpointadd
+ {\pgfqpointpolar{#3}{\forestove{l}}}%
+ {\pgfqpointpolar{\numexpr 90+#3\relax}{\forestove{s}}}%
+ }%
\pgfgetlastxy\forest at temp@x\forest at temp@y
\forestolet{x}\forest at temp@x
\forestolet{y}\forest at temp@y
@@ -6052,7 +7644,7 @@
\newdimen\forest at ys
\def\forest at setupgrowline#1{%
\edef\forest at grow{#1}%
- \pgfpointpolar\forest at grow{1pt}%
+ \pgfqpointpolar{\forest at grow}{1pt}%
\forest at xg=\pgf at x
\forest at yg=\pgf at y
\forest at xs=-\pgf at y
@@ -6245,6 +7837,7 @@
\let\forest at previous@px\forest at px
\let\forest at previous@py\forest at py
}
+\patchcmd{\pgfpointintersectionoflines}{\pgfpoint}{\pgfqpoint}{}{}
\def\forest at getnegativetightedgeofpath#1#2{%
\forest at get@onetightedgeofpath#1\forest at sort@ascending#2}
\def\forest at getpositivetightedgeofpath#1#2{%
@@ -6458,7 +8051,11 @@
\pgf at x=0pt
\fi
\fi
- \csname pgfmathatan2\endcsname{\pgf at x}{\pgf at y}%
+ \edef\forest at marshal{%
+ \noexpand\pgfmathatantwo@
+ {\expandafter\Pgf at geT\the\pgf at x}%
+ {\expandafter\Pgf at geT\the\pgf at y}%
+ }\forest at marshal
\let\forest at current@atan\pgfmathresult
\ifx\forest at last@atan\relax
\def\forest at last@x{#1}%
@@ -6501,7 +8098,7 @@
}%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@path
}%
\pgfsyssoftpath at getcurrentpath#2%
@@ -6514,7 +8111,7 @@
}%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@path
}%
\pgfsyssoftpath at getcurrentpath#2%
@@ -6531,13 +8128,13 @@
}%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@negpath
}%
\pgfsyssoftpath at getcurrentpath#2%
{%
\pgftransformreset
- \pgftransformrotate{\forest at grow}%
+ \forest at pgfqtransformrotate{\forest at grow}%
\forest at pgfpathtransformed\forest at gre@pospath
}%
\pgfsyssoftpath at getcurrentpath#3%
@@ -6751,7 +8348,7 @@
\def\forest at path@getboundingrectangle at ls#1#2{%
{%
\pgftransformreset
- \pgftransformrotate{-(#2)}%
+ \forest at pgfqtransformrotate{-#2}%
\forest at pgfpathtransformed#1%
}%
\pgfsyssoftpath at getcurrentpath\forest at gbr@rotatedpath
@@ -6775,6 +8372,17 @@
\ifdim#2<\pgf at ya\relax\pgf at ya=#2 \fi
\ifdim#2>\pgf at yb\relax\pgf at yb=#2 \fi
}
+\let\forest at pgfqtransformrotate\pgftransformrotate
+\let\forest at pgftransformcm\pgftransformcm
+\let\forest at pgf@transformcm\pgf at transformcm
+\patchcmd{\forest at pgfqtransformrotate}{\pgfmathparse{#1}}{\edef\pgfmathresult{\number\numexpr#1}}{}{}
+\patchcmd{\forest at pgfqtransformrotate}{\pgftransformcm}{\forest at pgftransformcm}{}{}
+\patchcmd{\forest at pgftransformcm}{\pgf at transformcm}{\forest at pgf@transformcm}{}{}
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\patchcmd{\forest at pgf@transformcm}{\pgfmathsetlength}{\forest at pgf@transformcm at setlength}{}{} % 4x
+\def\forest at pgf@transformcm at setlength#1#2{#1=#2pt}
\pgfkeys{/forest/external/.cd,
%copy command/.initial={cp "\source" "\target"},
copy command/.initial={},
@@ -6796,10 +8404,11 @@
}%
}{}%
}
+\newread\forest at copy@in
+\newwrite\forest at copy@out
\def\forest at file@copy@#1#2{%
- \newread\forest at copy@in
+ \begingroup
\openin\forest at copy@in=#1
- \newwrite\forest at copy@out
\immediate\openout\forest at copy@out#2
\endlinechar-1
\loop
@@ -6809,6 +8418,7 @@
\repeat
\immediate\closeout\forest at copy@out
\closein\forest at copy@in
+ \endgroup
}
\newif\ifforest at external@optimize@
\forest at external@optimize at true
@@ -6869,11 +8479,15 @@
\forest at next{#3}%
}
\def\forest at config#1{%
- \def\forest at stages{stages}%
+ \forest at defstages{stages}%
\forestset{@config/.cd,#1}%
}
+\def\forest at defstages#1{%
+ \def\forest at stages{#1}%
+}
\forestset{@config/.cd,
- stages/.store in=\forest at stages,
+ %stages/.store in=\forest at stages,
+ stages/.code={\forest at defstages{#1}},
.unknown/.code={\PackageError{forest}{Unknown config option for forest environment/command.}{In Forest v2.0.0 and v2.0.1, this (parenthesized) argument accepted the definition of style stages for the current forest environment/macro. Since v2.0.2, you should write "\string\begin{forest}(stages={...})...\string\end{forest}", or "\string\Forest(stages={...}){...}" instead.}}
}
\def\forest at group@env#1{{\forest at env{#1}}}
@@ -7094,9 +8708,9 @@
\pgfkeysvalueof{/pgf/inner xsep},\pgfkeysvalueof{/pgf/outer xsep}%
}
{
- l sep={\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}},
+ l sep'/.expanded={\the\dimexpr\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}},
l={l_sep()+abs(max_y()-min_y())+2*\pgfkeysvalueof{/pgf/outer ysep}},
- s sep={2*\pgfkeysvalueof{/pgf/inner xsep}}
+ s sep'/.expanded={\the\dimexpr \pgfkeysvalueof{/pgf/inner xsep}*2}
}
{l sep,l,s sep}
\pgfqkeys{/forest/@cs}{%
@@ -7111,11 +8725,11 @@
\forest at forestcs@resetxy},
anchor/.code={\forest at forestcs@anchor{#1}},
l/.code={%
- \pgfmathsetlengthmacro\forest at forestcs@l{#1}%
+ \forestmathsetlengthmacro\forest at forestcs@l{#1}%
\forest at forestcs@ls
},
s/.code={%
- \pgfmathsetlengthmacro\forest at forestcs@s{#1}%
+ \forestmathsetlengthmacro\forest at forestcs@s{#1}%
\forest at forestcs@ls
},
.unknown/.code={%
@@ -7130,8 +8744,8 @@
}
\def\forest at forestcs@resetxy{%
\ifnum\forest at cn=0 \forest at cs@invalidnodeerror\fi
- \global\pgf at x\forestove{x}%
- \global\pgf at y\forestove{y}%
+ \global\pgf at x\forestove{x}\relax
+ \global\pgf at y\forestove{y}\relax
}
\def\forest at forestcs@ls{%
\ifdefined\forest at forestcs@l
@@ -7138,8 +8752,8 @@
\ifdefined\forest at forestcs@s
{%
\pgftransformreset
- \pgftransformrotate{\forestove{grow}}%
- \pgfpointtransformed{\pgfpoint{\forest at forestcs@l}{\forest at forestcs@s}}%
+ \forest at pgfqtransformrotate{\forestove{grow}}%
+ \pgfpointtransformed{\pgfqpoint{\forest at forestcs@l}{\forest at forestcs@s}}%
}%
\global\advance\pgf at x\forestove{x}%
\global\advance\pgf at y\forestove{y}%
@@ -7233,10 +8847,18 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{children first}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children first}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children first}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children first}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{first}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{first}{\forest at referencednodeid}%
@@ -7245,14 +8867,26 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent first}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent first}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent first}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent last}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent last}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent last}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent last}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{last}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{last}{\forest at referencednodeid}%
@@ -7261,14 +8895,26 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children last}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children last}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children last}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{children'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{children first'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children first'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children first'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children first'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{first'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{first'}{\forest at referencednodeid}%
@@ -7277,14 +8923,26 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent first'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent first'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent first'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{parent last'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{parent last'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-parent last'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-parent last'}{\forest at referencednodeid}%
+}
\pgfdeclaregenericanchor{last'}{%
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{last'}{\forest at referencednodeid}%
@@ -7293,6 +8951,10 @@
\forest at anchor@forwardtotikztrue
\forest at anchor@do{#1}{children last'}{\forest at referencednodeid}%
}
+\pgfdeclaregenericanchor{-children last'}{%
+ \forest at anchor@forwardtotikztrue
+ \forest at anchor@do{#1}{-children last'}{\forest at referencednodeid}%
+}
\def\forest at anchor@do#1#2#3{% #1 = shape name, #2 = (potentially) forest anchor, #3 = node id
\forest at fornode{#3}{%
\def\forest at temp@anchor{#2}%
@@ -7322,10 +8984,20 @@
\forest at anchor@isbordertrue
\edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}}%
}
+\csdef{forest at anchor@@-children'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor{\number\numexpr 180+\forestove{grow}-\forestove{rotate}}%
+}
\csdef{forest at anchor@@parent'}{%
\forest at anchor@isbordertrue
- \edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@anchor{\number\numexpr\forest at temp@grow-\forestove{rotate}+180}%
}
+\csdef{forest at anchor@@-parent'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@anchor{\number\numexpr\forest at temp@grow-\forestove{rotate}}%
+}
\csdef{forest at anchor@@first'}{%
\forest at anchor@isbordertrue
\edef\forest at temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
@@ -7336,34 +9008,72 @@
}
\csdef{forest at anchor@@parent first'}{%
\forest at anchor@isbordertrue
- \edef\forest at temp@anchor at parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
- \edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}+180}%
+ \edef\forest at temp@anchor at first{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 -\else+\fi90}%
\forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at first}\forest at temp@anchor
}
+\csdef{forest at anchor@@-parent first'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}}%
+ \edef\forest at temp@anchor at first{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 -\else+\fi90}%
+ \forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at first}\forest at temp@anchor
+}
\csdef{forest at anchor@@parent last'}{%
\forest at anchor@isbordertrue
- \edef\forest at temp@anchor at parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}%
- \edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}+180}%
+ \edef\forest at temp@anchor at last{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 +\else-\fi90}%
\forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at last}\forest at temp@anchor
}
+\csdef{forest at anchor@@-parent last'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@grow{\ifnum\forestove{@parent}=0 \forestove{grow}\else\forestOve{\forestove{@parent}}{grow}\fi}%
+ \edef\forest at temp@reversed{\ifnum\forestove{@parent}=0 \forestove{reversed}\else\forestOve{\forestove{@parent}}{reversed}\fi}%
+ \edef\forest at temp@anchor at parent{\number\numexpr\forest at temp@grow-\forestove{rotate}}%
+ \edef\forest at temp@anchor at last{\number\numexpr\forest at temp@grow-\forestove{rotate}\ifnum\forest at temp@reversed=0 +\else-\fi90}%
+ \forest at getaverageangle{\forest at temp@anchor at parent}{\forest at temp@anchor at last}\forest at temp@anchor
+}
\csdef{forest at anchor@@children first'}{%
\forest at anchor@isbordertrue
\edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
\forest at getaverageangle{\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at first}\forest at temp@anchor
}
+\csdef{forest at anchor@@-children first'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor at first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}%
+ \forest at getaverageangle{180+\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at first}\forest at temp@anchor
+}
\csdef{forest at anchor@@children last'}{%
\forest at anchor@isbordertrue
\edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
\forest at getaverageangle{\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at last}\forest at temp@anchor
}
+\csdef{forest at anchor@@-children last'}{%
+ \forest at anchor@isbordertrue
+ \edef\forest at temp@anchor at last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}%
+ \forest at getaverageangle{180+\forestove{grow}-\forestove{rotate}}{\forest at temp@anchor at last}\forest at temp@anchor
+}
\csdef{forest at anchor@@children}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@children'}%
}
+\csdef{forest at anchor@@-children}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-children'}%
+}
\csdef{forest at anchor@@parent}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@parent'}%
}
+\csdef{forest at anchor@@-parent}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-parent'}%
+}
\csdef{forest at anchor@@first}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@first'}%
@@ -7376,43 +9086,69 @@
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@parent first'}%
}
+\csdef{forest at anchor@@-parent first}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-parent first'}%
+}
\csdef{forest at anchor@@parent last}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@parent last'}%
}
+\csdef{forest at anchor@@-parent last}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-parent last'}%
+}
\csdef{forest at anchor@@children first}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@children first'}%
}
+\csdef{forest at anchor@@-children first}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-children first'}%
+}
\csdef{forest at anchor@@children last}{%
\forest at anchor@snapbordertocompasstrue
\csuse{forest at anchor@@children last'}%
}
+\csdef{forest at anchor@@-children last}{%
+ \forest at anchor@snapbordertocompasstrue
+ \csuse{forest at anchor@@-children last'}%
+}
\def\forest at getaverageangle#1#2#3{%
\edef\forest at temp{\number\numexpr #1-#2+540}%
- \pgfmathMod{\forest at temp}{360}\pgfmathtruncatemacro\pgfmathresult{\pgfmathresult}
- \edef\forest at temp{360+#2+((\pgfmathresult-180)/2)}%
- \pgfmathMod{\forest at temp}{360}\pgfmathtruncatemacro#3{\pgfmathresult}%
+ \expandafter\pgfmathMod@\expandafter{\forest at temp}{360}%
+ \forest at truncatepgfmathresult
+ \edef\forest at temp{\number\numexpr 360+#2+((\pgfmathresult-180)/2)}%
+ \expandafter\pgfmathMod@\expandafter{\forest at temp}{360}%
+ \forest at truncatepgfmathresult
+ \let#3\pgfmathresult
}
+\def\forest at truncatepgfmathresult{%
+ \afterassignment\forest at gobbletoEND
+ \forest at temp@count=\pgfmathresult\forest at END
+ \def\pgfmathresult{\the\forest at temp@count}%
+}
+\def\forest at gobbletoEND#1\forest at END{}
\def\forest at anchor@border at to@compass{%
- \ifforest at anchor@isborder
+ \ifforest at anchor@isborder % snap to 45 deg, to range 0-360
\ifforest at anchor@snapbordertocompass
\forest at anchor@snap at border@to at compass
- \else
- \pgfmathMod{\forest at temp@anchor}{360}%
- \pgfmathtruncatemacro\forest at temp@anchor{\pgfmathresult}%
+ \else % to range 0-360
+ \pgfmathMod@{\forest at temp@anchor}{360}%
+ \forest at truncatepgfmathresult
+ \let\forest at temp@anchor\pgfmathresult
\fi
- \ifforest at anchor@forwardtotikz
- \ifcsname pgf at anchor%
- @\csname pgf at sh@ns@\pgfreferencednodename\endcsname
- @\csname forest at compass@\forest at temp@anchor\endcsname
- \endcsname
+ \ifforest at anchor@snapbordertocompass
+ \ifforest at anchor@forwardtotikz
+ \ifcsname pgf at anchor%
+ @\csname pgf at sh@ns@\pgfreferencednodename\endcsname
+ @\csname forest at compass@\forest at temp@anchor\endcsname
+ \endcsname
+ \letcs\forest at temp@anchor{forest at compass@\forest at temp@anchor}%
+ \fi
+ \else
\letcs\forest at temp@anchor{forest at compass@\forest at temp@anchor}%
\fi
- \else
- \ifforest at anchor@snapbordertocompass
- \letcs\forest at temp@anchor{forest at compass@\forest at temp@anchor}%
- \fi
\fi
\fi
}
@@ -7426,11 +9162,12 @@
\csdef{forest at compass@315}{south east}
\csdef{forest at compass@360}{east}
\def\forest at anchor@snap at border@to at compass{%
- \pgfmathMod{\forest at temp@anchor}{360}%
- \pgfmathdivide{\pgfmathresult}{45}%
- \pgfmathround{\pgfmathresult}%
- \pgfmathmultiply{\pgfmathresult}{45}%
- \pgfmathtruncatemacro\forest at temp@anchor{\pgfmathresult}%
+ \pgfmathMod@{\forest at temp@anchor}{360}%
+ \pgfmathdivide@{\pgfmathresult}{45}%
+ \pgfmathround@{\pgfmathresult}%
+ \pgfmathmultiply@{\pgfmathresult}{45}%
+ \forest at truncatepgfmathresult
+ \let\forest at temp@anchor\pgfmathresult
}
\def\forest at anchor@forward#1{% #1 = shape name
\ifdefempty\forest at temp@anchor{%
@@ -7452,34 +9189,32 @@
\if\relax#2\relax#1\fi
}
\expandafter\def\expandafter\forest at referencednodename@stripafter\expandafter#\expandafter1\forest at pgf@notyetpositioned\relax{#1}
+\def\forest at pointanchor#1{% #1 = anchor
+ \forest at Pointanchor{\forest at cn}{#1}%
+}
\def\forest at Pointanchor#1#2{% #1 = node id, #2 = anchor
- {%
- \def\forest at pa@temp at name{name}%
- \forestOifdefined{#1}{@box}{%
- \forestOget{#1}{@box}\forest at temp
- \ifdefempty\forest at temp{}{%
- \def\forest at pa@temp at name{later at name}%
+ \def\forest at pa@temp at name{name}%
+ \forestOifdefined{#1}{@box}{%
+ \forestOget{#1}{@box}\forest at temp
+ \ifdefempty\forest at temp{}{%
+ \def\forest at pa@temp at name{later at name}%
+ }%
+ }{}%
+ \setbox0\hbox{%
+ \begin{pgfpicture}% this is expensive: so that's why caching
+ \if\relax\forestOve{#1}{#2}\relax
+ \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{center}%
+ \else
+ \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{\forestOve{#1}{#2}}%
+ \fi
+ \xdef\forest at global@marshal{%
+ \noexpand\global\noexpand\pgf at x=\the\pgf at x\relax
+ \noexpand\global\noexpand\pgf at y=\the\pgf at y\relax\relax
}%
- }{}%
- \setbox0\hbox{%
- \begin{pgfpicture}%
- \if\relax\forestOve{#1}{#2}\relax
- \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{center}%
- \else
- \pgfpointanchor{\forestOve{#1}{\forest at pa@temp at name}}{\forestOve{#1}{#2}}%
- \fi
- \xdef\forest at global@marshal{%
- \noexpand\global\noexpand\pgf at x=\the\pgf at x\relax
- \noexpand\global\noexpand\pgf at y=\the\pgf at y
- }%
- \end{pgfpicture}%
- }%
+ \end{pgfpicture}%
}%
\forest at global@marshal
}
-\def\forest at pointanchor#1{% #1 = anchor
- \forest at Pointanchor{\forest at cn}{#1}%
-}
\ifdefempty{\forest at compat}{}{%
\RequirePackage{forest-compat}
}
More information about the tex-live-commits
mailing list