5

I am trying to write some macros that in turn automatically generate other macros, depending on options etc.

I wonder, if it's possible to use \NewDocumentCommand{\somename}{\standardargs}, i.e. the argument list itself is 'hidden' in a macro.

Here is a non-working, short example (the non-necessary overhead is removed, of course)

\documentclass{article}

\usepackage{xparse}

\newcommand{\standardargs}{O{}+m}

\NewDocumentCommand{\somecmd}{\standardargs}{%
  % Do something more or less useful
  My args: #2
}


\begin{document}
\somecmd{Hello World}
\end{document}

The error message is

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! LaTeX error: "xparse/unknown-argument-type"
! 
! Unknown argument type '\standardargs' replaced by 'm'.
! 
! See the LaTeX3 documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

l.10 }

Some notes

  • I am pretty sure, this is some expansion problem
  • I am aware that I might have to use a more sophisticated approach to maintain the {} brackets as optional value default specifiers for \NewDocumentCommand.
  • The usage/usability of such a standard argument list might be doubtful, I would agree with that.
  • As I wrote already in my question and the comments by egreg and Joseph Wright point to the same direction: It's possible, but not advisable to use this strategy. – user31729 Apr 30 '15 at 14:48
5

Yes, expand the macro before \NewDocumentCommand tries to grab the second (macro definition) argument:

\documentclass{article}

\usepackage{xparse}

\newcommand{\standardargs}{O{}+m}

\expandafter\NewDocumentCommand\expandafter\somecmd\expandafter{\standardargs}{%
  % Do something more or less useful
  My args: #2
}


\begin{document}
\somecmd{Hello World}
\end{document}
  • Werner, I could swear, I had such statements. Even in conjunction with the fact, that this should be even inside, defining the the macro actually, i.e. \expandafter\NewDocumentCommand\csname SomeCommand#1\expandafter\endcsname\expandafter{\standardargs}, but perhaps I was missing one \expandafter at the right position – user31729 Apr 29 '15 at 21:05
  • I will have a look tomorrow, it's late here already – user31729 Apr 29 '15 at 21:06
6

It is exactly an expansion problem. Here's the definition of \NewDocumentCommand:

\cs_new_protected:Npn \NewDocumentCommand #1#2#3
  {
    \cs_if_exist:NTF #1
      {
        \__msg_kernel_error:nnx { xparse } { command-already-defined }
          { \token_to_str:N #1 }
      }
      { \__xparse_declare_cmd:Nnn #1 {#2} {#3} }
  }

It would be very easy to define a variation that accepts an argument to be expanded, if \__xparse_declare_cmd:Nnn was among the public functions, but it isn't. Without going against the programming conventions you could do it yourself:

\ExplSyntaxOn
\cs_set_eq:NN \hupfer_newdocumentcommand:Nnn \NewDocumentCommand
\cs_generate_variant:Nn \hupfer_newdocumentcommand:Nnn { No }
\NewDocumentCommand\NewDocumentCommandExp{mmm}
 {
  \hupfer_newdocumentcommand:Non #1 { #2 } { #3 }
 }
\ExplSyntaxOff

and then your syntax

\NewDocumentCommandExp{\somecmd}{\standardargs}{%
  % Do something more or less useful
  My args: #2
}

would work. What this can be useful for, I really don't know.

  • 2
    Of course, this is entirely against the spirit of xparse: the point is that the interfaces should be documented as part of the code itself. – Joseph Wright Apr 29 '15 at 21:39
  • 1
    @JosephWright Agreed: this is a wrong approach to xparse. On the other hand, I can vaguely see applications for \NewNamedDocumentCommand that gets as its first argument a command name ( c style, to be clearer) in case one has to build a series of commands from some variable data. – egreg Apr 29 '15 at 21:53
  • @egreg: Yes, it's an abuse of the benefits of xparse. I will use another strategy for the relevant code. Thanks for your explicit and quick answer! – user31729 Apr 30 '15 at 14:47
5

l3 allows you to avoid \expandafter

\documentclass{article}

\usepackage{xparse}

\newcommand{\standardargs}{O{}+m}

\ExplSyntaxOn
\def\MyNewDocumentCommand{\exp_args:NNo\NewDocumentCommand}
\ExplSyntaxOn
\MyNewDocumentCommand{\somecmd}{\standardargs}{%
  % Do something more or less useful
  My args: #2
}


\begin{document}
\somecmd{Hello World}
\end{document}
  • Thanks, David. I think, I should switch to expl3 for my project anyway. – user31729 Apr 30 '15 at 14:46

Your Answer

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