22

I am looking to define a command (actually, an environment, but that shouldn't matter for the purposes of this question) that does some default behavior, and if an optional argument is passed, does something else.

For example,

\newcommand{mycommand}[1]{%
if (#1 != NULL){%
The argument #1 was passed}
else {%
No argument was passed.}}

Obviously this is not valid LaTeX, but hopefully this makes it clear what I am trying to do. Is there a way to do this with ordinary LaTeX? Is it worth switching to LuaLaTeX to accomplish behavior like this?

1

3 Answers 3

25

You can do it easily with xparse:

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\mycommand}{o}{%
  % <code>
  \IfNoValueTF{#1}
    {code when no optional argument is passed}
    {code when the optional argument #1 is present}%
  % <code>
}

\begin{document}

\mycommand

\mycommand[HERE]

\end{document}

This will print

code when no optional argument is passed
code when the optional argument HERE is present

For an environment it's similar

\NewDocumentEnvironment{myenv}{o}
  {\IfNoValueTF{#1}{start code no opt arg}{start code with #1}}
  {\IfNoValueTF{#1}{end code no opt arg}{end code with #1}}

Other code common to the two cases can be added at will. As you see, xparse also allows (but it's not mandatory) to use the argument specifiers also in the end part.

22
\makeatletter
\newcommand{\mycommand}[1][\@nil]{%
  \def\tmp{#1}%
   \ifx\tmp\@nnil
       no argument
    \else
         argument #1
    \fi}
\makeatother



\mycommand zzzz \mycommand[hello]  zzz
7
  • 5
    What is the command \@nnil ? Commented Dec 12, 2014 at 22:29
  • 1
    @sergiokapone: That was a minor typo on David's side :) The default optional argument should just match whatever you use against the test; \relax would have worked just as well.
    – Werner
    Commented Dec 12, 2014 at 22:33
  • 4
    @Werner no sorry it was not a typo, and \relax would not work as well, I reverted the edit. \@nnil is defined in the latex format by \def\@nnil{\@nil} for exactly this test Commented Dec 12, 2014 at 22:46
  • @sergiokapone \@nnil is \def\@nnil{\@nil} so it is equal to \tmp if the default argument of \@nil is used in the case the command has no explicit argument. Commented Dec 12, 2014 at 22:48
  • 2
    @DavidCarlisle: Sorry, I was too eager to add some mortar to your brick.
    – Werner
    Commented Dec 12, 2014 at 22:50
2

Here's a solution using the LaTeX internal \@ifnextchar:

\documentclass{minimal}
\makeatletter
\def\foo{\@ifnextchar[\foo@BT\foo@BF}
\def\foo@BT[#1]{Bracket true. Optional argument was: #1.}
\def\foo@BF{Bracket false. No optional argument.}
\makeatother

\begin{document}
\foo[Hello, world]

\foo
\end{document}
1
  • 1
    Please do not use minimal for examples as it is not suitable for this purpose.
    – cfr
    Commented Dec 12, 2014 at 23:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .