I often find myself in need of a \noexpand utility that works on a TeX group rather than a macro. For example, in my current project, I have subroutines:
% adds a box to the layer
\newcommand\addbox[1] {
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {#1};
}
}
\expandafter\addcodetolayer\drawboxcode
}
% pushes object code onto layer
\newcommand\addcodetolayer[1]
{\seq_gput_right:Nn\sq__layercmds{#1}}
% renders layer
\newcommand\renderlayer
{\seq_use:Nnnn \sq__layercmds{}{}{}}
I require these because the code I use to draw TikZ objects is divided into subroutines that place content on multiple PGF layers (e.g. a box on one layer, a shadow on another layer) in an interleaved way and, unfortunately, every time the \begin{pgfonlayer}{foolayer} environment is used, it wipes out any content in the foolayer layer previously written.
My recourse has been to use the subroutines above in the following way:
\begin{tikzpicture}
\addbox {Foo Box}
\addbox {Bar Box}
...
\begin{pgfonlayer}{boxlayer}
\renderlayer
\end{pgfonlayer}
\end{tikzpicture}
This works well but has one outstanding problem: the argument to \addbox, if it contains macros such as \ref, must have these manually \noexpand-ed to avoid errors, i.e.
\addbox {Foo Box (section~\ref{sec:foo})} % gives horrible cryptic LaTeX errors
\addbox {Foo Box (section~\noexpand\ref{sec:foo})} % works like a charm
Ideally I would like to avoid this, but I know of no good way to do it. The most obvious fix would be if \noexpand could work on TeX groups rather than macros, but it doesn't. Using
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {\noexpand{#1}};
}
}
does nothing, for instance. I also can't use
\def\drawboxcontent{#1}
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {\noexpand\drawboxcontent};
}
}
because when \drawboxcontent is finally expanded in \renderlayer, the macro will only contain the content of the last added box.
This is just one example of where a utility that prevents \edef from expanding a block of code (i.e. TeX group) rather than a macro would be extremely useful.
One alternative would be a utility that allowed code such as
\passbyvaluedef\drawboxcontent{#1}
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {\drawboxcontent};
}
}
where \passbyvaluedef would define a macro \drawboxcontent that, when expanded, would expand into some unique command sequence \drawboxcontentaaaa without expanding further, and \drawboxcontentaaaa would contain whatever was in #1. The next time \passbyvaluedef\drawboxcontent was called, \drawboxcontent would expand into \drawboxcontentaaab, and so on, returning a unique CS name in each case. This is less elegant than a group-based \noexpand, but it would also get the job done.
Are there any TeX/LaTeX macros/packages for doing either of these things (effectively \noexpand-ing groups, or the suggested alternative)? If not, is there another way to solve the problem of having to manually include \noexpands in my box contents, or am I stuck with them?
unexpanded's behavior is like\the\toks0instead of like\noexpandeach token, which is the same inside an\edef(which is the case here) but might be different in other cases e.g. tex core - Why is \unexpanded not respected after an \if? - TeX - LaTeX Stack Exchange. – user202729 Aug 06 '22 at 11:19