7

I keep getting illegal parameter errors when trying to define a command that contains another previously defined command. I know that you have to be careful with nested definitions, but I didn't think I was doing that. Here is the MWE:

\documentclass{memoir}

\usepackage{xstring,xparse,xspace}

\NewDocumentCommand{}{\pfc}{Preface~\StrGobbleLeft{#1}{1}\xspace}

\NewDocumentCommand{\D}{ o }{%
\IfNoValueTF{#1} {%
\emph{D}\xspace}{%
    \IfBeginWith{#1}%
    {p}{\emph{D} \pfc}{%
        \IfStrEqCase{#1}{%
            {f}{\emph{Daybreak}\xspace}%
            {g}{\emph{Morgenröte}\xspace}%
            }%
            [\emph{D}~#1\xspace]%
        }%
    }%
}

\begin{document}

\D[p1]

I was expecting the following:

D Preface 1

But I just get the illegal parameter errors. Presumably I don't want to use ##1 because I am not renewing a command within the macro. If I just put the content of \pfc instead of the command into the \D command, then it works, but I don't want to do this.

Any ideas?

  • what do you want \pfc to be? You have defined it as a command taking no arguments but used #1 in the definition so get an error, just as you would with \newcommand or \def Possibly you want to define \pfc as a macro taking one argument and then use \pfc{#1} in your second definition, to pass that argument on. – David Carlisle Dec 2 '13 at 11:33
  • I want \pfc just to stand in for Preface~\StrGobbleLeft{#1}{1}\xspace. I tried using \newcommand, but got the same error. I have used \NewDocumentCommand in the way used above to define commands that do not take arguments elsewhere and it works fine. – DavidR Dec 2 '13 at 11:36
  • 1
    You can't use #1 to pass the argument from \D to \pfc. Either you have to define an auxiliary storage macro or define \pfc to take an argument and pass it through, so \NewDocumentCommand{\pfc}{m}{...} and then \pfc{#1} in the definition of \D. – Loop Space Dec 2 '13 at 11:39
  • That worked, thanks! Just out of interest, why can't #1 be used to pass the argument through? – DavidR Dec 2 '13 at 11:43
  • 2
    Basically when TeX sees \foo{aaa} where \foo is a macro taking one argument, it removes \foo{aaa} from the input stream and replaces it with the replacement text for \foo with #1 replaced by aaa this is done first then TeX starts processing that replacement text having forgotten all about \foo. So by the time it sees \pfc inside your definition and expands it, all association of #1 to the argument of the top level command is forgotten. – David Carlisle Dec 2 '13 at 11:59
8

You have defined it as a command taking no arguments but used #1 in the definition so get an error, just as you would with \newcommand or \def.

To pass the argument of the outer command on to \pfc you need to define \pfc as a macro taking one argument and then use \pfc{#1} in your second definition, to pass that argument on.

So

\NewDocumentCommand{\pfc}{m}{... #1 ...}

....

 ....\pfc{#1}

Basically when TeX sees \foo{aaa} where \foo is a macro taking one argument, it removes \foo{aaa} from the input stream and replaces it with the replacement text for \foo with #1 replaced by aaa. This is done first, then TeX starts processing that replacement text having forgotten all about \foo. So by the time it sees \pfc inside your definition and expands it, all association of #1 to the argument of the top level command is forgotten.

2

There's an obvious error in the definition of \pfc, which however doesn't seem a really useful command by its own.

You get a simpler implementation by fully using expl3:

\documentclass{memoir}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{xparse,xspace}

\ExplSyntaxOn
\NewDocumentCommand{\D}{ o }
 {
  \IfNoValueTF{#1}
   {% No optional argument: just print D
    \emph{D}\xspace
   }
   {% Optional argument: pass control to an inner function
    \rowthorn_D:n { #1 }
   }
 }

\cs_new:Npn \rowthorn_D:n #1
 {% Check what's the first token in the optional argument
  \str_case_x:nnF { \tl_head:n { #1 } }
   {% if it's `p', remove it and print the rest
    {p}{\emph{D}\nobreakspace Preface\nobreakspace\tl_tail:n { #1 }}
   }
   {% otherwise, if it's f or g ...
    \str_case:nnF { #1 }
     {
      {f}{\emph{Daybreak}}% it's `f': print Daybreak
      {g}{\emph{Morgenr\"ote}}% it's `g': print Morgenröte
     }
     {\emph{D}\nobreakspace#1}% otherwise print the whole argument
   }
 }
\ExplSyntaxOff

\begin{document}

\D[p1] xyz

\D[f] xyz

\D xyz

\D[g] xyz

\D[ff] xyz

\end{document}

Note that \xspace is needed only in the “no optional argument” case (if ever).

enter image description here

  • The reasoning behind \pfc was that I have around 20 commands equivalent to \D for different books. If I want to change the way references to the preface of a book are formatted, I don't want to have to change all 20 commands. Your solution, to be honest, is beyond my LaTeX level at the moment, but it looks good :) – DavidR Dec 2 '13 at 21:29

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.