5

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?

4
  • 2
    do you look for \unexpanded? Commented Aug 5, 2020 at 17:03
  • @UlrikeFischer: Never heard of it. I'll look it up. Thanks.
    – COTO
    Commented Aug 5, 2020 at 17:06
  • @UlrikeFischer: Sonuvagun. Works perfectly. Thanks. If you'd put it in an official answer, I'll happily give you the green check. :)
    – COTO
    Commented Aug 5, 2020 at 17:10
  • Side note, unexpanded's behavior is like \the\toks0 instead of like \noexpand each 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
    Commented Aug 6, 2022 at 11:19

1 Answer 1

10

You can use \unexpanded{<balanced text>}. This will avoid the expansion in the <balanced text>.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .