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.

I'd like to concatenate several parts of math text into a single command, and i read a great solution here on this site, allowing me to create this working example of what i mean :

\documentclass[a4paper,10pt]{report}
\usepackage[francais]{babel}

\def\reptemp{I love rain}
\global\edef\reptemp{\reptemp, but not too much.}

\begin{document}
\reptemp
\end{document} 

Unfortunately for some reason it refuses to work with more complex things in it, for example

\documentclass[a4paper,10pt]{report}
\usepackage[francais]{babel}

\def\reptemp{I {\it love} rain}
\global\edef\reptemp{\reptemp, but \bf{not} too much.}

\begin{document}
\reptemp
\end{document} 

produce the following error message

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
l.16 \reptemp
?

Of course i'd like to concatenate complex things by this method (environment, enumerate, etc) and i wonder if its possible.

share|improve this question
2  
In addition to Marco's point about \bf, you should also be careful with local versus global definitions. Either the macro is local (so \def and \edef), or global (so \gdef and \xdef, as 'abbreviations' for \global\def and \global\edef). –  Joseph Wright Sep 30 '12 at 7:54

3 Answers 3

up vote 12 down vote accepted

What you want to achieve can be done in several ways. First of all let me start with a small hint: The commands \bf and it are obsolete and they don't have an argument. Please see this answer: Despite using backslash dollar sign, error persists


First of all you have to decide whether to save the contents in a token or a command. The differences and some explanation to your question are well explained by the great answer of Joseph Wright. Is \toks necessary to define \g@addto@macro? Can token registers be avoided in generel?


Using a command:

Approach 1: using \g@addto@macro:

\g@addto@macro is defined in the LaTeX Kernel. Based on the protected sign @ you have to use \makeatletter ... \makeatother, see: What do \makeatletter and \makeatother do?

\documentclass[a4paper,10pt]{report}
\makeatletter
\def\reptemp{I \textit{love} rain}
\g@addto@macro\reptemp{, but \textbf{not} too much.}
\makeatother
\begin{document}
\reptemp
\end{document} 

Approach 2: using package etoolbox:

The package etoolbox defines some helper macros to add new information to a given command. The material can be added before and after the command. Egreg provides a more robust package with the same functionality. The package is called xpatch. He also provides a more powerful package with is declared as experimental version, the package regexpatch.

Here an example with etoolbox:

\documentclass[a4paper,10pt]{report}
\usepackage{etoolbox}
\def\reptemp{I \textit{love} rain}
\appto\reptemp{, but \textbf{not} too much.}
\begin{document}
\reptemp
\end{document} 

The package etoolbox provides more useful functionality and can be loaded with xpatch too.


A special and new modern way is the usage of macros of the project LaTeX3 and the language expl3. Here you can work with token register as well as sequences. The range is really big. The usage of the new syntax needs some special handling which is explained in the short manual expl3. Of course you will find a lot of related questions here at tex.stackexchange.

share|improve this answer

this will work:

\documentclass{report}

\def\reptemp{I {\itshape love} rain}
\expandafter\def\expandafter\reptemp\expandafter{\reptemp, but {\bfseries not} too much.}

\begin{document}
\reptemp
\end{document} 

it expands first the old definition of \reptemp before defining the new one

share|improve this answer

Just an addition to Marco Daniel's excellent answer.

The technique with \edef is perfectly fine if all we need is to append (or prepend, or both) to a string of characters. It can work with other tokens, but let's limit ourselves to a simple application:

\def\mystring{} % initialize
\def\extendmystring#1#2{\edef\mystring{#1\mystring#2}}

Then

\extendmystring{I love rain}{}
\extendmystring{}{, but not too much.}
\extendmystring{``}{''}

would result in \mystring expanding to

``I love rain, but not too much.''

However this is not the right tool if you want to preserve the structure of what we're storing.

The command \textit (which should be used instead of \it in your example) expands into the instructions needed for persuading TeX into printing the argument in italic type. Even if \textif survived in \edef, you'd lose some information.

Let's see an example which somewhat works with \edef. The code

\def\mand#1#2{#1 or #2} % "macro and"
\def\mystring{I love \mand{rain}{snow}} % reinitialize
\extendmystring{``}{, but not too much.''}

will result in \mystring expanding to

``I love rain and snow, but not too much.''

and the information that "rain" and "snow" are arguments to \mand is completely lost. In a real world application, one might rely on having \mand in the replacement text and redefine it before expanding (using) \mystring; if \mand is retained, it would be easy to say

\def\mand#1#2{#2}

and using \mystring would print

``I love snow, but not too much.''

while keeping the information intact in \mystring. This won't happen with the \edef technique.

The problem is that \edef expands macros (expandable tokens, to be precise) all the way down to unexpandable tokens. Macros like \textit (as well as the obsolete \it) don't survive an \edef for reasons that are rather difficult to explain in a few words.

If you want to preserve information, then the \preto and \appto road is surely better.

share|improve this answer

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.