17

\aftergroup executes the next token after the end of the current group. Is there a variant, \Vaftergroup{\some\tokens\a\b} that would put \some\tokens\a\b after the current group ends? Of course, one can do \aftergroup\some\aftergroup\tokens\aftergroup\a\aftergroup\b, but when the list is longer, it becomes messy.

This is motivated by an answer that works but is ugly.

  • 1
    mark wooding's doafter package was designed after he had asked this question some time in the 80s. it's conceivable he did it without benefit of etex (which would have been very new at the time, if it existed at all) – wasteofspace May 14 '13 at 9:21
16

In much the same vein as Herbert's answer, a 'pre-built' version of the same idea is provided by the etextools package: see \AfterGroup. I guess that \aftergroup is used rarely enough that this has not been a big demand :-)

  • studying this package will teach me much about the fine points of expansion, I believe :). Thanks for the info! – Bruno Le Floch Jan 2 '11 at 23:24
  • 5
    @Bruno ...or else drive you mad :) – Will Robertson Jan 3 '11 at 2:04
  • 1
    The \AfterGroup macro solves the problem in the way outlined by Herbert, but defining a new global temporary macro each time (via a counter) which is then undefined at use time. – egreg May 14 '13 at 9:21
10

don't know if this might help.

\documentclass{article}

\def\ta{Hello}
\def\tb{ World. }
\def\tc{How are you?}
%\def\Tokens{\ta\tb\tc}

\begin{document}

\begingroup
\gdef\Tokens{\ta\tb\tc}% or like above with def
\aftergroup\Tokens
\let\ua=\tc
\let\ub=\tb
\let\uc=\ta
\ua\ub\uc---\par
\endgroup

\end{document}
  • 4
    Thanks. This is what I ended up doing, but I didn't like the idea of a global temporary variable: bad things can happen before the group is finished. – Bruno Le Floch Jan 2 '11 at 22:55
7

Put this in your preamble

% Usage
% \Aftergroup{ balanced text }
% \Aftergroup token text token 
%                    where text is any row of tokens and token is a character that is not in text (compare \verb)
%
% Example:
% \Aftergroup {\aaa{bbb}} and \Aftergroup @\aaa{bbb}@ put \aaa{bbb} after the endgroup
% whereas \Aftergroup }\aaa{bbb}} and \Aftergroup \egroup\aaa{bbb}} put \aaa{bbb after the second "}"
%
% For the unbalanced text a problem is that we can not distinguish "{" and "\bgroup" (or 
% "}"and "\egroup". Hence by
% Aftergroup @\bgroup \egroup@ the tokens inserted after the group are "{}" and by
% Aftergroup \bgroup \egroup @\bgroup the tokens "}@ are put after the group.  

\makeatletter

\def\Aftergroup{\bgroup
    \let\Bgroup={\let\bgroup}%give \bgroup a different meaning, } to balance
    \@ifnextchar\Bgroup
        {\egroup\@AGBalancedText}
        {\@ifnextchar\egroup
            {\egroup\def\@AGdelimiter{\egroup}\afterassignment\@AGDelNextToken\let\@let@token=}
            {\egroup\@AGDelimited}}
}

\def\@AGDelimited#1{\def\@AGdelimiter{#1}\@AGDelNextToken}

\def\@AGDelNextToken{%
    \expandafter\@ifnextchar\@AGdelimiter{\let\@let@token=}%end
       {\@ifnextchar\bgroup
        {\aftergroup{\iffalse}\fi\afterassignment\@AGDelNextToken\let\@let@token=}
        {\@ifnextchar\egroup
            {\iffalse{\fi\aftergroup}\afterassignment\@AGDelNextToken\let\@let@token=}
            {\@AGDeltoken}
}}}

\def\@AGDeltoken#1{\aftergroup#1\@AGDelNextToken}

\def\@AGBalancedText#1{\@AGBalNextToken#1{\@AGBalNextToken}}

\def\@AGBalNextToken#1#{\@AGBalNotOpen#1\@AGBalNotOpen\@AGBalClose}

\def\@AGBalNotOpen#1{\ifx\@AGBalNotOpen#1\else\aftergroup#1\expandafter\@AGBalNotOpen\fi}

\def\@AGBalClose#1{%
    \ifx\@AGBalNextToken#1\relax%
    \else\ifx\@AGBalClose#1\relax\iffalse{\else\aftergroup}\fi
            \expandafter\expandafter\expandafter\@AGBalNextToken%
        \else\iftrue\aftergroup{\else}\fi\@AGBalNextToken#1{\@AGBalClose}%
        \fi
    \fi
}

\makeatother

The following code

{\Aftergroup }\def\aaa{123}}\relax}\show\aaa
{\Aftergroup {\def\aaa{123\bgroup\egroup}}}\show\aaa
{\Aftergroup @\def\aaa{123\bgroup\egroup}@}\show\aaa

then gives

 > \aaa=macro:
 ->123\relax .
 l.102 {\Aftergroup }\def\aaa{123}}\relax}\show\aaa

 ? 
 > \aaa=macro:
 ->123\bgroup \egroup .
 l.103 ...p {\def\aaa{123\bgroup\egroup}}}\show\aaa

 ? 
 >\aaa=macro:
 ->123{}.
 l.104 ...p @\def\aaa{123\bgroup\egroup}@}\show\aaa

in the output window of TeX.

1

Below there is an alternative. \Tokens remains local.

\documentclass{article}

\def\ta{Hello}
\def\tb{ World. }
\def\tc{How are you?}
%\def\Tokens{\ta\tb\tc}

\begin{document}

\begingroup
\def\Tokens{\ta\tb\tc}% or like above with def
\let\ua=\tc
\let\ub=\tb
\let\uc=\ta
\ua\ub\uc---\par
\expandafter\endgroup\Tokens

\show\Tokens
\end{document}
  • 2
    This requires that you 'know' where the end-of-group is (and is going to be tricky to pull off in box/\halign contexts). Herbert's answer is 'general' in the sense you don't need to know where or how the group is going to end. – Joseph Wright May 14 '13 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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