Wednesday, March 5, 2008

Newcommand with an optional argument

I don’t know why this feature is not implemented in LaTeX. You can very easily define your own commands, but they may take only a fixed number of arguments (up to 9). Bad luck, because the first command I needed to write for my dissertation had to have an optional argument:

Linguists traditionally write words and sounds from a language of interest in italics, e.g. the N|uu word ainki. Often it is followed by an enquoted translation, e.g. ainki ‘father’, xainki ‘mother’, n|ai ‘see’, and kx’ain ‘laugh’ all contain the diphthong ai.

So I wanted to write me a command \nuu by which I could write either just the N|uu word in italics or the word in italics followed by the enquoted translation. I would use it either just as \nuu{ainki} for ainki or as \nuu[father]{ainki} for ainki ‘father’.

Later, when I learn how to make an index of all N|uu words written in my document, I probably will just add an indexing command into the \nuu command definition. For now the optional argument was trouble enough. I did not expect that it will involve hardcore TeX programming.

Fortunately good people from the xetex@tug.org mailing list have suggested some solutions for this and the most bullet-proof and versatile was this (thanks to Morten Høgholm and Ross Moore):


\documentclass{article}

\makeatletter
\long\def\tlist@if@empty@nTF #1{%
\expandafter\ifx\expandafter\\\detokenize{#1}\\%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}

\providecommand*\nuu[2][]{%
\textit{#2}%
\tlist@if@empty@nTF{#1}{}{ `#1'}% only the false code executed
}
\makeatother

\begin{document}
\nuu{ainki} \nuu[mother]{xainki} \nuu[goat]{mudi}
\end{document}


I use \providecommand instead of \newcommand. I feel safer. “It works like \newcommand, but if the command is already defined, LaTeX2e will silently ignore it.” (Oetiker et al., lshort.pdf, p. 109.)

13 comments:

KEDJI Komlan Akpédjé said...

This feature is implemented in LaTeX2e, see http://tex.loria.fr/ctan-doc/macros/latex/doc/html/usrguide/node18.html

Unknown said...

No, it isn't. What they call an "optional argument" ist just the default value of a mandatory argument:

Thus the usage of \example is either:

\example{BBB}

which prints:

Mandatory arg: BBB; Optional arg: YYY.

or:

\example[XXX]{AAA}

which prints:

Mandatory arg: AAA; Optional arg: XXX.

kyanh said...

There is an easier way that uses \ifnextchar to test for optional argument. You may read the example in TeX by Topic.

KEDJI Komlan Akpédjé said...

@sven: I understand now. The two features look quite similar, and the terminology used by LaTeX is rather confusing.

Anonymous said...

You might want to have a look at:
http://www.ctan.org/tex-archive/support/newcommand/

Christoph Jahn said...

Very nice, thanks. I started using LaTeX in 1992 but until now have always avoided optional arguments. Makes my life quite a bit easier :-)

Anonymous said...

Congrats and many thanks for posting this piece of code : I happened to stumble upon the same problem and your post saved my day.

Anonymous said...

The xparse package (from LaTeX3) provides a powerful general solution to this problem via replacements for \newcommand and its siblings. A variety of required and optional argument types can be included in macro definitions.

writing a good research paper said...

I think TeX is one popular means by which to typeset complex mathematical formulae; it has been noted as one of the most sophisticated digital typographical systems in the world

online custom writing service said...

Great server, and most importantly very necessary for both beginners and for prof. One can only wish, "" Work and more!

Anonymous said...

In that case it seems simple enough to have two separate command. One that takes one argument and one that takes two, as in \nuu and \nuutwo.

Anonymous said...

Might I recommend the xifthen package. It defines the commands you need (avoids use of makeatletter):

\documentclass{article}
\usepackage{xifthen}% provides \ifthenelse and \isempty

\providecommand*\nuu[2][]{%
\textit{#2}%
\ifthenelse{\isempty{#1}}{}{ `#1'}%
}

\begin{document}
\nuu{ainki} \nuu[mother]{xainki} \nuu[goat]{mudi}
\end{document}

Samuel Brown said...

Thank you very much for sharing this! Very helpful