views:

1055

answers:

3

I'm trying to write a simple example command that prints nothing without an argument, but with an argument it surrounds it with something.

I've read that the default value should be \@empty and the simple \ifx\@empty#1 condition should do the job:

\newcommand{\optarg}[1][\@empty]{%
\ifx\@empty#1  {}  \else  {(((#1)))}  \fi
}

\optarg % (((empty)))
\optarg{} % (((empty)))
\optarg{test} % (((empty))) test

The latter three commands all print the empty word for some reason, and I want the first two to print nothing and the last to print (((test))).

I'm using TeXLive/Ubuntu. An ideas?

+1  A: 

In the underlying TeX engine with which LaTeX is written, the number of arguments a command can take is fixed. What you've done with the default [\@empty] is ask LaTeX to examine the next token to see if it is an open square bracket [. If so, LaTeX takes the contents of square brackets as the argument, if not, the next token is put back into the input stream and the default \@empty argument is used instead. So to get your idea to work, you have to use square brackets to delimit the optional argument when present:

\optarg
\optarg[]
\optarg[test]

You should have better luck with this notation.

It's annoying that you can't use the same brackets for an optional argument as you use for a required argument, but that's the way it is.

Norman Ramsey
Wow, thank you! Never thought brackets are so important. However, the problem remains: `\optarg` still gives me `(((empty)))` and `\optarg[]=((()))` (afaik this should not work anyway). Only `\optarg[test]` is now `(((test)))` as expected.
o_O Tync
Try `\ifx!#!\else(((#1)))\fi` and make the default arg `!`. If that works you can change the `!` to something that someone is less likely to use by accident.
Norman Ramsey
+2  A: 

Try the following test:

\documentclass{article}

\usepackage{xifthen}% provides \isempty test

\newcommand{\optarg}[1][]{%
  \ifthenelse{\isempty{#1}}%
    {}% if #1 is empty
    {(((#1)))}% if #1 is not empty
}

\begin{document}

Testing \verb|\optarg|: \optarg% prints nothing

Testing \verb|\optarg[]|: \optarg[]% prints nothing

Testing \verb|\optarg[test]|: \optarg[test]% prints (((test)))

\end{document}

The xifthen package provides the \ifthenelse construct and the \isempty test.

Another option is to use the ifmtarg package (see the ifmtarg.sty file for the documentation).

godbyk
Works like a charm, thank you! :)
o_O Tync
+2  A: 

Using the LaTeX3 xparse package:

\usepackage{xparse}
\NewDocumentCommand\optarg{g}{%
  \IfNoValueF{#1}{(((#1)))}%
}
Joseph Wright
Thank you, that works too, but is designed to be used in packages AFAIK.
o_O Tync
The aim of xparse is to provide a complete alternative to \newcommand. There is no reason you can't use it for a one-off command in the preamble of a document: I certainly do (but then I did write most of the current implementation of xparse, although I'd stress that the ideas are not really mine). The example in the documentation are mainly about packages at the moment, but I've written a TUGBoat article for the next issue that has some "document" uses.
Joseph Wright