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?

COTO
  • 371

1 Answers1

10

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

Ulrike Fischer
  • 327,261