# \xdef with arguments in \newcommand?

Considering this newcommand (it works fine)

\newcommand\createCMDSH[4]{%
\expandafter\@ifdefinable\csname #3#2\endcsname{%
\expandafter\xdef\csname #3#2\endcsname{%
\noexpand\vcenteredhbox{\noexpand\includegraphics[height=\noexpand\taille,trim=0 0 1 -1]{BD_CATIA/#4/#1.png}}%
}%
}%
}


I can obtain a command with a name specified by #3#2 for displaying a picture.

The idea is to change the xdef command for building a new #3#2 command with one argument. How can I do this? Is xdef the right command?

Explanation (#3#2=cmdperso):

• old version \cmdperso{}
• new version \cmdperso{0.5} (50% of the \textwidth)

I have tried this but it is not working:

\newcommand\createCMDM[4]{%
\expandafter\@ifdefinable\csname #3#2\endcsname{%
\expandafter\xdef\csname #3#2\endcsname[1][]{%
\noexpand\includegraphics[width=\noexpand##1\textwidth]{BD_CATIA/#4/#1.png}%
}%
}%
}


SOLUTION

\newcommand\createCMDM[4]{%
\expandafter\@ifdefinable\csname #3#2\endcsname{%
\expandafter\xdef\csname #3#2\endcsname##1{%
\noexpand\includegraphics[width=##1\noexpand\hsize]{BD_CATIA/#4/#1.png}%
}%
}%
}

• Since you're expanding nothing in the replacement text for \xdef, what are you using it for? – egreg Jan 30 '15 at 12:10
• In fact I call \createCMDM using: \createCMDM{...}{\txtA}{\txtB}{...} and \txtA and \txtB contain perso and cmd. But maybe I misunderstand the expand process. – Guuk Jan 30 '15 at 12:15

You combine the \newcommand syntax of parameter declarations with \xdef primitive. But primitive commands have normal and elegant syntax without square brackets.

\def\createCMDM#1#2#3#4{% I don't understand why #3 is merged with #2
\expandafter\@ifdefinable\csname #3#2\endcsname{%
\expandafter\gdef\csname #3#2\endcsname##1{%
\includegraphics[width=##1\hsize]{BD_CATIA/#4/#1.png}%
}%
}%
}


If you are using \cmdperso{} for full \hsize and \cmdperso{0.5} for half \hsize, then you don't need to implement the optional parameter.

Edit: I replace \xdef to \gdef and remove one \noexpand. The \xdef is not needed here.

• Actually, the OP needs \xdef, as explained in the last comment to the question. – egreg Feb 1 '15 at 10:35

You could create an emulation of what \newcommand with two optional argument does, but I think it's better using xparse and expl3 for this:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\createCMDSH}{mmmm}
{
\guuk_create_cmdsh:cxx { #3#2 } { #1 } { #4 }
}

\cs_new_protected:Nn \guuk_create_cmdsh:Nnn
{
\NewDocumentCommand{#1}{}
{
\vcenteredhbox{
\includegraphics[height=\taille,trim=0~0~1~-1]{BD_CATIA/#3/#2.png}
}
}
}
\cs_generate_variant:Nn \guuk_create_cmdsh:Nnn { cxx }

\NewDocumentCommand{\createCMDM}{mmmm}
{
\guuk_create_cmdm:cxx { #3#2 } { #1 } { #4 }
}

\cs_new_protected:Nn \guuk_create_cmdm:Nnn
{
\NewDocumentCommand{#1}{O{}}
{
\vcenteredhbox{
\includegraphics[width=##1\textwidth]{BD_CATIA/#3/#2.png}
}
}
}
\cs_generate_variant:Nn \guuk_create_cmdm:Nnn { cxx }
\ExplSyntaxOff

\newcommand{\txtA}{TEXTA}
\newcommand{\txtB}{TEXTB}
\createCMDSH{\txtA}{\txtB}{X}{Y} % this will create \XTEXTB

\createCMDM{\txtA}{\txtB}{ZZZ}{WWW} % this will create \ZZZTEXTB


The command \ZZZTEXTB will have an optional argument, so \ZZZTEXTB would print the image \textwidth wide, while \ZZZTEXTB[0.5] will print it half of the textwidth.

• Thanks but Can I use the same syntax as I used in my first command? Just by adding some argument? – Guuk Jan 30 '15 at 12:38
• @Guuk If you want a regular (braced) argument, just add ##1 after \endcsname, instead of [1][]. With the xparse/expl3 approach it's easier to manage expansions. – egreg Jan 30 '15 at 13:47