2

I would like to be able to change the content of the nodes, from a home made parameter list to an actual text.

For example, I would like to create trees such as:

\documentclass{standalone}
\usepackage{forest}

\begin{document}
\begin{forest}
[9;12;4
    [31;21]
    [3
        [14]
        [7;21;3]
    ]
]
\end{forest}
\end{document}

enter image description here

will be formatted this way:

enter image description here

Basically, depending on the number of parameters, separated by a semi-column, I would like to format the final content differently:

  • with 1 parameter, format is "#1 is the one"
  • with 2 parameters, format is "with #1[#2]"
  • with 3 parameters, format is "$#2 \geq #1$ for #3 cases"

So far, I managed to split the content of each node with split option, but I did not succeed to know how many I actually have, and access each of them.

What I am looking for is something like:

before typesetting nodes={
   for tree={
       split option={content}{;}{params},
       if {length(params) = 1}{content=params[1] is the one}{
           if {length(params) = 2}{content=with params[1][params[2]]}{
               if {length(params} = 3}{content=$params[2] \geq params[1]$ for params[3] cases}
               {}
            }
        }  
    }
}

PS: The reason I am trying to do that in such way it's because I need to create a lot of big trees with the same node format. And from a writer perspective, it is much easier to just chose the parameters of each nodes and keep the formatting separated, especially if you have to change it later.

bill0ute
  • 123
  • 4

2 Answers2

3

split option (and other split keys) "zip" the given "instruction" keylist (their #3) and the "parameter" list (in the option case, the split value of the option given as their #1). The parts of the option can thus be processed by different keys.

\documentclass{standalone}
\usepackage{forest}

\forestset{
  declare toks register=param1,
  declare toks register=param2,
  declare toks register=param3,
  gobble/.style={},
  my split/.style={
    param1={},
    param2={},
    param3={},
    split option={content}{;}{param1,param2,param3,gobble},
    if param2={}{
      content'/.process=Rw1{param1}{##1 is the one}
    }{
      if param3={}{
        content'/.process=R2w2{param1}{param2}{with ##1[##2]}
      }{
        content'/.process=R3w3{param1}{param2}{param3}{$##2 \geq ##1$ for ##3 cases}
      }
    }
  }
}

\begin{document}
\begin{forest} delay={for tree=my split}
[9;12;4
    [31;21]
    [3
        [14]
        [7;21;3]
    ]
]
\end{forest}
\end{document}
2

I am not sure if split option works with lists of different dimensions. (I am not sure really means that I do not know.) However, you could split the contents with xstring. (I also added a patch that removes spurious spaces; in later versions of pgf this will no longer be needed.)

\documentclass{standalone}
\usepackage{forest}
\usepackage{xstring}
\makeatletter
% remove the stray space https://tex.stackexchange.com/a/513549
\patchcmd{\pgfutilsolvetwotwoleqfloat}
  { \noexpand\pgfmathfloatdivide@}
  {\noexpand\pgfmathfloatdivide@}
  {}{}
\makeatother
\begin{document}
\begin{forest}
before typesetting nodes={
    for tree={
        content/.wrap value={\StrCount{#1}{;}[\mydim]%
        \StrSubstitute{#1}{;}{,}[\mytemp]%
        \ifcase\mydim
         \pgfmathsetmacro{\myone}{{\mytemp}[0]}\myone\ is the one
        \or
         \pgfmathsetmacro{\myone}{{\mytemp}[0]}%
         \pgfmathsetmacro{\mytwo}{{\mytemp}[1]}%
         {with \myone[\mytwo]}
        \or
         \pgfmathsetmacro{\myone}{{\mytemp}[0]}%
         \pgfmathsetmacro{\mytwo}{{\mytemp}[1]}%
         \pgfmathsetmacro{\mythree}{{\mytemp}[2]}%
         {$\mytwo\geq\myone$ for \mythree\ cases}
        \fi}}}
[9;12;4
    [31;21]
    [3
        [14]
        [7;21;3]
    ]
]
\end{forest}
\end{document}

enter image description here

Or a version that works with strings, too.

\documentclass{standalone}
\usepackage{forest}
\usepackage{xstring}
\makeatletter
% remove the stray space https://tex.stackexchange.com/a/513549
\patchcmd{\pgfutilsolvetwotwoleqfloat}
  { \noexpand\pgfmathfloatdivide@}
  {\noexpand\pgfmathfloatdivide@}
  {}{}
\makeatother
\def\pfttwo#1;#2|{\def\myone{#1}\def\mytwo{#2}}%
\def\pftthree#1;#2;#3|{\def\myone{#1}\def\mytwo{#2}\def\mythree{#3}}%
\begin{document}
\begin{forest}
before typesetting nodes={
    for tree={
        content/.wrap value={\StrCount{#1}{;}[\mydim]%
        \ifcase\mydim
         \pgfmathsetmacro{\myone}{#1}\myone\ is the one
        \or
         \pfttwo#1|%
         {with \myone[\mytwo]}
        \or
         \pftthree#1|%
         {$\mytwo\geq\myone$ for \mythree\ cases}
        \fi}}}
[9;12;4
    [31;21]
    [3
        [14]
        [7;21;3]
    ]
]
\end{forest}
\end{document}
  • 1
    Any extras go to the last thing, so you can process a list of n items with a parsing list of one and all n will be sent, one after the other, to the one. (Which is a very confusing way of saying it.) – cfr Dec 05 '19 at 04:00