0

I am trying to add a variable number of fields to a bytefield, inside a TikZ Node. An earlier question (Using foreach to add variable number of rows to a bytefield inside a TikZ node?) gave helpful hints, but I still don't get it to work. So, here a more detailed example.

\documentclass[tikz]{standalone}

\usepackage{bytefield}

\usetikzlibrary{positioning}

\begin{document}

% What I want to achieve, written out without loops: % (inelegant, does not scale to the large number of nodes % for which I need this) \begin{tikzpicture}

\node [draw] (a) {a}; \node [draw] at (6,0) (b) {b};

\node [below=of a] { \begin{bytefield}{8} \wordbox{1}{Source: b} \ \wordbox{1}{1} \ \wordbox{1}{2} \ \wordbox{1}{3} \end{bytefield} };

\node [below=of b] { \begin{bytefield}{8} \wordbox{1}{Source: a} \ \wordbox{1}{4} \ \wordbox{1}{5} \end{bytefield} }; \end{tikzpicture}

% What should be a step in the right direction, % compare https://tex.stackexchange.com/questions/679919/using-foreach-to-add-variable-number-of-rows-to-a-bytefield-inside-a-tikz-node/679923?noredirect=1#comment1687472_679923

\begin{tikzpicture}[wordbox/.code={\\wordbox{1}{#1}}] \node { \begin{bytefield}{8} \wordbox{1}{Source: A} \tikzset{wordbox/.list={1,2,3}} \end{bytefield} }; \end{tikzpicture}

% How I hope to get it to work, but only get two wordboxes, % instead of four on the left, three on the right: \begin{tikzpicture}[wordbox/.code={\\wordbox{1}{#1}}]

\node [draw] (a) {a}; \node [draw] at (6,0) (b) {b};

\foreach \n/\fields in {a/{1,2,3},b/{4,5}} { \node [below=of \n] { \begin{bytefield}{8} \wordbox{1}{Source: \n} \tikzset{wordbox/.list=\fields} \end{bytefield} }; } \end{tikzpicture}

% An alternative with a foreach inside bytefield does not even compile: % \begin{tikzpicture}

% \node [draw] (a) {a}; % \node [draw] at (6,0) (b) {b};

% \foreach \n/\fields in {a/{1,2,3},b/{4,5}} { % \node [below=of \n] { % \begin{bytefield}{8} % \wordbox{1}{Source: \n} % \foreach \f in \fields { \ \wordbox{1}{\f} } % \end{bytefield} % }; % } % \end{tikzpicture}

\end{document}

Example figures for the three steps see below.

In the last case, it seems that the list handler does not iterate over the fields? Any way to fix that?

What I want:

What I want

Intermediate step in the right direction?

Intermediate step in the right direction?

What I get:

What I get

1 Answers1

0

If you just say /.list=\fields, the macro \fields will be the only element of your list. Internally, this will lead to a loop that looks like

\foreach \ELEMENT in {\fields}

You need to expand \fields at least once before the .list handler should evaluate it. Thus, you need

\tikzset{wordbox/.list/.expand once=\fields}

or

\tikzset{wordbox/.list/.expanded=\fields}

Your second example (with an explicit \foreach loop) leads to problems because it will group each iteration. It would be similar to

\begin{bytefield}{8}
  \wordbox{1}{Source: \n}
  { \\ \wordbox{1}{1} }
  { \\ \wordbox{1}{2} }
  { \\ \wordbox{1}{3} }
\end{bytefield}

which conflicts on how bytefield works internally.

If you're not satisfied with .list (which uses PGFFor's \foreach internally and would allow the ... syntax) you could use for example \int_step_inline:nnn used as such:

% Preamble
\ExplSyntaxOn
\DeclareDocumentCommand{\ForeachInline}{}{\int_step_inline:nnn}
\ExplSyntaxOff

% Document \begin{tikzpicture} \node [draw] (a) {a}; \node [draw] at (6,0) (b) {b};

\foreach \n/\st/\en in {a/1/3, b/4/5} { \node [below=of \n] { \begin{bytefield}{8} \wordbox{1}{Source: \n} \ForeachInline{\st}{\en}{ \ \wordbox{1}{##1} } \end{bytefield} }; } \end{tikzpicture}

Qrrbrbirlbel
  • 119,821