13

After a lot of trial and error, I haven't been able to solve the following problem:
A simplified version: I want to use \g@addto@macro to add code to another macro wich will use a command of the macro, I expected this code to work:

\newcommand{\foo}[1]{#1, }
\newcommand{\bar}[1]{
    \g@addto@macro\foo{
        ##1#1
    }
}

And to produce this output:

\foo{A} -> A,
\bar{B}
\show\foo = #1, #1B
\foo{A} -> A, AB
\bar{C}
\show\foo = #1, #1B#1C
\foo{A} -> A, ABAC

I hope it is clear what I want. In an actual implementation, I want to expand a \switch-like structure dynamically. The problem with the code is, that the ## is not expanded to # when adding code, however #1 is expanded to the first parameter of \bar. This causes

\bar{B}
\show\foo = #1, ##1B

wich in turn doesn't produce the desired output. I would like to avoid additional packages if possible.

2
  • Egreg's provided a solution but I'll note that apart from the problem with # you are missing several % which would add spurious space tokens to your result. \g@addto@macro goes to some lengths passing the tokens through a toks register specifically to prevent the need to double # (so you can build up strings including that character) Feb 6, 2014 at 1:57
  • @DavidCarlisle In my original code I had the comments in; thanks for the advice though :)
    – AlexR
    Feb 6, 2014 at 2:04

2 Answers 2

9

\g@addto@macro uses a token register to stop the interpretation of # that you want.

You just want \def.

\documentclass{article}

\begin{document}

\newcommand{\foo}[1]{#1, }

\def\zfoo#1\relax{\long\def\foo##1{#1}}
\newcommand{\baR}[1]{%
   \expandafter\zfoo\foo{##1}##1#1\relax
}

\foo{A}
\show\foo


\baR{B}
\show\foo %= #1, #1B

\foo{A} %-> A, AB

\baR{C}
\show\foo% = #1, #1B#1C

\foo{A} %-> A, ABAC


\end{document}

which produces

> \foo=\long macro:
#1->#1, .
l.13 \show\foo

? 
> \foo=\long macro:
#1->#1, #1B.
l.17 \show\foo
               %= #1, #1B
? 
> \foo=\long macro:
#1->#1, #1B#1C.
l.22 \show\foo
              % = #1, #1B#1C
? 

enter image description here

10

No, you can't append tokens to a macro with parameters using \g@addto@macro. Nor you can do it with \apptocmd of etoolbox.

You can do it with regexpatch, though.

\documentclass{article}
\usepackage{regexpatch}

\newcommand{\foo}[1]{#1,\space}
\newcommand{\baz}[1]{%
  \def\temp{#1}%
  \regexpatchcmd{\foo}{ \Z }{ \cP\#1 \u{temp} }{}{}%
}


\begin{document}

\foo{A}

\baz{B}\foo{A}

\baz{C}\foo{A}

\end{document}

The "search" regular expression matches the end of the replacement text; this is replaced by \cP\#1 (which means #1 with the correct category codes) followed by the expansion of the macro \temp. Thus I set \temp to the argument of \baz.

Unfortunately, the current version of regexpatch can't patch macros whose replacement text ends with a space, so in this particular case I used \space at the beginning.

Here's the output:

enter image description here

3
  • Thanks for the answer. So there's no way to, say manually set the catcode at the specific position? Or to adapt the code of \g@addto@macro? Seems like a serious flaw to me...
    – AlexR
    Feb 6, 2014 at 0:26
  • @AlexR Serious flaw (of LaTeX2e itself probably, but certainly of many packages) is the need for patching.
    – yo'
    Feb 6, 2014 at 0:33
  • @AlexR it was written that way so you could use \newcommand in \AtBeginDocument in a way that you didn't have to have multiple doubling of #. Feb 6, 2014 at 2:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .