Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

\newcommand / \newenvironment - optional parameters

Tags:

I'm experimenting with my own commands and environments and now I'm facing those problems:

  1. How to create command \foo{parameter}[optional] or environment called \begin{bar}{parameter}[optional]?
  2. How to create command \foo[optional_1]...[optional_n]{parameter}

I've tried

\newcommand{\foo}[3][][]{#1#2#3}    - failed
\newcommand{\foo}[3][2][][]{#1#2#3} - failed

Does anyone know some hint? Thanks a lot.

like image 471
Crowley Avatar asked May 25 '10 22:05

Crowley


2 Answers

  1. You can't create a \foo{parameter}[optional] command simply; you can, however, create a \foo[optional]{parameter} command with

    \newcommand{\foo}[2][def]{Mandatory: #2; optional: #1}
    

    If you call it as \foo{given}, it will produce Mandatory: given, optional: def; if you call it as \foo[optional]{given}, it will produce Mandatory: given, optional: optional. This is probably how you should do it—that will look better with the rest of your LaTeX code. Creating a new environment with optional parameters is done similarly with

    \newenvironment{env}[2][def]{(#1,#2)\begingroup}{\endgroup}
    

    where # is again the optional argument; this is again written as \begin{env}[opt]{req}...\end{env}. If you really want a command in the other form, see the end of my answer.

  2. The TeX FAQ has an answer about writing commands with more than one optional argument. There are two options to how to do it. The underlying idea is to define a command which takes an optional argument, and then runs another command which itself takes an optional argument, etc.; the twoopt package encapsulates this.


If you really want a command like \reversed{mandatory}[optional], you can do it like so. First, you define a command which takes a required argument, stores it in a macro, and then forward it onto another command. This second command takes an optional argument, and uses the defined command and the optional argument. Putting this all together, we get

\makeatletter
\newcommand{\reversed}[1]{\def\reversed@required{#1}\reversed@opt}
\newcommand{\reversed@opt}[1][def]{Required: \reversed@required; optional: #1}
\makeatother

You can then use \reversed{mandatory}[optional] or just \reversed{mandatory}, and everything should work.

like image 124
Antal Spector-Zabusky Avatar answered Sep 18 '22 23:09

Antal Spector-Zabusky


Using the xparse package (part of the LaTeX3 development efforts):

\usepackage{xparse}
\NewDocumentCommand\foo{O{}O{}m}{%
  % Code with optional #1 and #2 with empty defaults
}
\NewDocumentCommand\foo{mO{}}{%
  % Code with optional #2 with empty default
}
\NewDocumentEnvironment{foo}{O{}}{%
% Start code with optional #1
}{%
%  End code with optional #1
}

Optional arguments are a bit different in xparse to with \newcommand. You can detect whether one is given or not:

\NewDocumentCommand\foo{mo}{%
  \IfNoValueTF{#2}
   {Code without #2}
   {Code with #2}%
}

You'll see that this works by using a lower case 'o', whereas the upper case 'O' then requires a default value (which I've made empty by including an empty group).

like image 24
Joseph Wright Avatar answered Sep 22 '22 23:09

Joseph Wright