Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
add comment

3 Answers

up vote 10 down vote accepted

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}
share|improve this answer
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
add comment

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.

share|improve this answer
add comment

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}
share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.