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 want to create a macro \foo which creates another macro which a custom name set just before the execution of \foo via a macro \defcommand{myCustomName} and saves/adds something to it just as the following pseudo-latex-code suggests. Is it possible to translate this to a working LaTeX example?

%\defcommand needs to be defined
%addtocommand needs to be defined
\newcommand{\foo}[1]{
%If the command \???CustomString??? doesn't exist, create it and then add the content of #1 to it.
\addtocommand{???CustomString???}{#1}
}

Some text

\defcommand{customA}
\foo{A1} \foo{A2} \foo{A3} %should create a command named `customA` (instead of ???CustomString???) which I can use in the whole document. 

\customA %this schould print A1 A2 A3    

some text...

\defcommand{customB}
\foo{B1},\foo{B2} %now \foo should create another command named `customB`...

\customB %should print A1 A2 A3

\customA %should print B1 B2

Note that I don't want to use an argument of \foo to do this. I.e. I don't want to write \foo{Ax}{\customA}.

share|improve this question
    
A syntax such as \foo{A}{1} would be preferable, unless the prefix is always one letter only. –  egreg Oct 1 '12 at 14:26
    
In my use cases I would have to write lots of foo's wit the same second argument. For example \foo{A1}{\mymacroA} \foo{A2}{\mymacroA} \foo{A3}{\mymacroA}... so in my case it would much easier to write something like \defcommand{\mymacroA} and then just \foo{A1} \foo{A2} \foo{A3}... –  student Oct 1 '12 at 14:32

1 Answer 1

up vote 8 down vote accepted

If the prefix is always one letter, then you can do it:

\makeatletter
\newcommand{\defcommand}[1]{\@namedef{custom#1}{}}
\newcommand{\foo}[1]{\@foo#1\@nil}

\def\@foo#1#2\@nil{%
  \expandafter\ifx\csname custom#1\endcsname\@empty
    \expandafter\g@addto@macro\csname custom#1\endcsname{#1#2}%
  \else
    \expandafter\g@addto@macro\csname custom#1\endcsname{ #1#2}%
  \fi}
\makeatother

\defcommand{A}
\foo{A1}\foo{A2}\foo{A355}

\defcommand{B}
\foo{B123} \foo{Ba} \foo{B3}

\show\customA
\show\customB

This will print on the terminal

> \customA=macro:
->A1 A2 A355.
l.19 \show\customA

? 
> \customB=macro:
->B123 Ba B3.
l.20 \show\customB

Of course this wouldn't work if one wants

\defcommand{ABC}

and \foo{ABC1}, because it wouldn't be possible to know what's the prefix.

If the prefix may consist of more than one letter, I suggest a different syntax:

\makeatletter
\newcommand{\defcommand}[1]{\@namedef{custom#1}{}}
\newcommand{\foo}[2]{%
  \expandafter\ifx\csname custom#1\endcsname\@empty
    \expandafter\g@addto@macro\csname custom#1\endcsname{#1#2}%
  \else
    \expandafter\g@addto@macro\csname custom#1\endcsname{ #1#2}%
  \fi}
\makeatother

\defcommand{A}
\foo{A}{1}\foo{A}{2}\foo{A}{355}

\defcommand{ABC}
\foo{ABC}{123} \foo{ABC}{a} \foo{ABC}{3}

\show\customA
\show\customABC

This will print on the terminal

> \customA=macro:
->A1 A2 A355.
l.17 \show\customA

? 
> \customABC=macro:
->ABC123 ABCa ABC3.
l.18 \show\customABC

If the intent is to establish a macro to which subsequent calls should add, then it's a different matter.

\makeatletter
\newcommand{\defcommand}[1]{%
  \gdef#1{}%
  \gdef\foo@current@command{#1}%
}
\newcommand{\foo}[1]{%
  \expandafter\ifx\foo@current@command\@empty
    \expandafter\g@addto@macro\foo@current@command{#1}%
  \else
    \expandafter\g@addto@macro\foo@current@command{ #1}%
  \fi
}
\makeatother

\defcommand{\macroA}
\foo{x} \foo{y} \foo{z}

\defcommand{\macroB}
\foo{Here}\foo{is}\foo{a}\foo{new}\foo{one}

\show\macroA
\show\macroB

This will print on the terminal

> \macroA=macro:
->x y z.
l.21 \show\macroA

? 
> \macroB=macro:
->Here is a new one.
l.22 \show\macroB

The trick is to define \foo always in terms of the same wrapper command, and to add to \defcommand a part that defines the wrapper command as the current macro that's initialized.

How does this last set of macros work? Let's see it in slow motion.

  1. Here's \defcommand:

    \newcommand{\defcommand}[1]{%
      \gdef#1{}%
      \gdef\foo@current@command{#1}%
    }
    

    If we say \defcommand{\mymacro} the effect will be to initialize \mymacro to have empty expansion. Then the (global) definition will make \foo@current@command expand to \mymacro (not to the contents of \mymacro, at least at the first expansion).

  2. Here's \foo

    \newcommand{\foo}[1]{%
      \expandafter\ifx\foo@current@command\@empty
        \expandafter\g@addto@macro\foo@current@command{#1}%
      \else
        \expandafter\g@addto@macro\foo@current@command{ #1}%
      \fi
    }
    

    This has some complications, so let's look at a simplified version:

    \newcommand{\foo}[1]{%
      \expandafter\g@addto@macro\foo@current@command{#1}%
    }
    

    One has to know that \g@addto@macro adds its second argument to the (parameterless) macro given as first argument. So, assume we have declared \defcommand{\mymacro} and then we do \foo{x}: this becomes

    \expandafter\g@addto@macro\foo@current@command{x}
    

    and now \expandafter comes into action, changing \foo@current@command to its first level expansion, which gives \mymacro, so now we have

    \g@addto@macro\mymacro{x}
    

    which does the desired thing.

  3. The more complex definition is used to ensure that no space is added in front of the first item we add:

    \newcommand{\foo}[1]{%
      \expandafter\ifx\foo@current@command\@empty
        \expandafter\g@addto@macro\foo@current@command{#1}%
      \else
        \expandafter\g@addto@macro\foo@current@command{ #1}%
      \fi
    }
    

    Let's see assuming that now \defcommand{\bar} has just been given, so that now \foo@current@command expands to \bar, whose expansion is empty. As soon as we say \foo{abc}\foo{def}, TeX will transform it into

    \expandafter\ifx\foo@current@command\@empty
      \expandafter\g@addto@macro\foo@current@command{#1}%
    \else
      \expandafter\g@addto@macro\foo@current@command{ #1}%
    \fi
    \foo{def}
    

    The first \expandafter changes \foo@current@command into \bar:

    \ifx\bar\@empty
      \expandafter\g@addto@macro\foo@current@command{abc}%
    \else
      \expandafter\g@addto@macro\foo@current@command{ abc}%
    \fi
    \foo{def}
    

    Now \bar has empty expansion, so the "true" branch is followed:

    \expandafter\g@addto@macro\foo@current@command{abc}%
    \foo{def}
    

    and, again,

     \g@addto@macro\bar{abc}\foo{def}
    

    so that, now, the expansion of \bar will be abc and TeX will examine \foo{def}. This will do exactly the same as before, but following the "false" branch, because \bar is no longer empty. So we'll have

    \expandafter\g@addto@macro\foo@current@command{ def}
    

    that becomes

    \g@addto@macro\bar{ def}
    

    and the final result will be the same as if we had said

    \def\bar{abc def}
    

    to begin with.

share|improve this answer
    
I just realized that my question was not clear enough... The first character in the argument of \foo doesn't have to match the (last character) of the custom macro. I.e. \defcommand{A} \foo{one}\foo{two}\foo{three} should add one two three to the macro \A (or \customA) –  student Oct 1 '12 at 17:35
    
@student Maybe the third version is what you need. –  egreg Oct 1 '12 at 17:59
    
Yes that is what I want! Thanks! –  student Oct 1 '12 at 19:34
    
...but I don't really understand why this works. With my very limited TeX knowledge I think that: When I call \defcommand{\macroA}, TeX creates an empty macro named \macroA and then puts this empty content to another macro called \foo@current@command. When then \foo{x} is called, \foo@current@command will contain x. When I finaly call \macroA I would expect that it prints nothing. I guess that \gdef\foo@current@command\macroA somehow ensures that \macroA contains everything of \foo@current@command since the last call of \defcommand but I don't see why. –  student Oct 1 '12 at 20:03
    
Perhaps this is because my understanding of the \def command is to limited... Would be nice if you could add some more explanations that I can grasp why it works. –  student Oct 1 '12 at 20:04

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.