Use \bgroup and \egroup to set some pre and post code to a macro

Why isn’t it possible to use \bgroup and \egroup in this way?

\documentclass{article}

\def\precode{\fbox\bgroup}
\def\postcode{\egroup}

\newcommand{\mymacro}[1]{\precode#1\postcode}

\begin{document}
\mymacro{Text}
\end{document}


I know that I can store the argument to a box or smiley use \fboxin the definition of \mymacro directly but the application of this MWE is a little more complex so that these two way won’t work. Now I wonder why this code gives no error but gives no text either.

-

AFAIK, only a few commands, say, TeX box primitives like \hbox, can use \bgroup and \egroup like this. An example:

\newcommand\premybox{\leavevmode\hbox\bgroup\bfseries(}
\newcommand\postmybox{)\egroup}

\premybox hello\postmybox


However, \mbox and \fbox, and other macros cannot be used like this. See TeX Hacks's Blog for new definitions of \mbox and \fbox which allow this usage.

You can use environ package to get the content between two macros. And this simpler TeXnique is also useful:

\def\precode #1\postcode{something about #1}

-
@egreg and Leo: Thank you both! In this case I‘ll us another way: defining an internal command that takes the argument of \mymacro like \enclosecode{#1}. Both answers are useful, but I think Leo’s matches my question a little better since \fbox was only a place holder, so I’ll accept his answer … –  Tobi Mar 3 '12 at 12:44

You can't because \fbox is defined by

\newcommand\fbox[1]{%
\leavevmode\setbox\@tempboxa\hbox{%
\color@begingroup\kern\fboxsep{#1}\kern\fboxsep\color@endgroup}%
\@frameb@x\relax}


With \mymacro{Text} you do \precode Text\postcode which becomes

\fbox\bgroup Text\egroup


But \bgroup is not an argument delimiter here: only explicit braces are. So \bgroup is taken as #1 and you get the wrong token list.

If the color package is not loaded, \color@begingroup and \color@endgroup are defined to be \relax, so what you get next is

\leavevmode\setbox\@tempboxa\hbox{%
\color@begingroup\kern\fboxsep{\bgroup}\kern\fboxsep\color@endgroup}%
\@frameb@x\relax Text\egroup


Inside \hbox, \bgroup acts as a group delimiter and is balanced by the } just next to it. The final \egroup closes the \hbox{, so this explains why you don't get any output.

If the color package is loaded, \color@begingroup becomes \begingroup and \color@endgroup becomes \endgraf\endgroup; if you try, you'll get an error, because the groups are not properly balanced.

-

You can do this by lying to TeX about what you mean by \precode and \postcode:

\documentclass{article}

% egreg's clever macros
\def\obrace{\iftrue{\else}\fi}
\def\cbrace{\iffalse{\else}\fi}

\def\precode#1\postcode{%
\edef\next{\noexpand\fbox\obrace\unexpanded{#1}\cbrace}%
\next
}

\newcommand{\mymacro}[1]{\precode#1\postcode}

\begin{document}
\mymacro{Text}
\end{document}

-
Of course it works, but I can't see why the simpler \newcommand{\mymacro}[1]{\fbox{#1}} can't be considered. Here this trick is clearly overkill. –  egreg Mar 3 '12 at 17:50
I interpreted the question to mean that he needed the syntax \precode#1\postcode for other reasons. –  Ryan Reich Mar 3 '12 at 17:52