Optional parameter in newcommand

\newcommand{\mysec}[2]{%
\textbf{#1} \\ #2
}


I use it with \mysec{A}{B}.

But sometimes I also want a third parameter. I could make a whole new command for those situations where I need 3 parameters. But I thought if I could handle it with an optional parameter in my original command?

So I have to check if the third parameter is set and how to print if it is set.

• If you are trying to make up your own sectioning commands, this is the worst way. What should the third argument do? – egreg Nov 22 '15 at 11:26

Optional parameters are in [] not {} and if using \newcommand always come first.

so

\newcommand{\mysec}[3][]{%
\textbf{#2} \\ #3 #1%
}


allows

\mysec{aaa}{bbb}


or

\mysec[ccc]{aaa}{bbb}

• Thanks. How do I check if it's empty? I have tried \ifx#1\empty\else\MakeUppercase{#1}\fi – Jamgreen Nov 22 '15 at 12:01
• @Jamgreen Lots of ways, there are questions on site about that:-) your suggestion tests \empty and \else if #1 is empty, i would use \ifx\relax#1\relax which is true if #1 is empty as then \relax tests equal to \relax, if you need to protect against #1 being \relax you need a bit more complicated, but normally you don't... – David Carlisle Nov 22 '15 at 12:03
• @Jamgreen note however if this is a section heading, better to use the section heading commands, just using \\  allows page breaks after the heading and misses all the other features latex normally takes care of. – David Carlisle Nov 22 '15 at 12:06

I suggest to use xparse and \RenewDocumentCommand with provides easier ways to define macros with optional arguments

The argument specification somo says to use a starred (#1), optional (#2), mandatory (#3) and a final optional argument (#4), if needed.

Redefining the sectioning commands should be done with care since they provide a starred variant which is used for example in \tableofcontents as a 'heading'

Instead of \@ifnextchar[ it's necessary to use \IfValueTF{#2}{true}{#4} to ask whether the optional argument #2 was used or not.

\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}

\let\origsection\section

\RenewDocumentCommand{\section}{somo}{%
\IfBooleanTF{#1}{%
\origsection*{#3}%
\IfValueTF{#4}{%
\textcolor{red}{You used the starred version and the 4th optional argument: }\textcolor{violet}{#4}%
}{%
%      \textcolor{blue}{You used the starred version but omitted the 4th one}%
}
}{%
\IfValueTF{#2}{%
\origsection[#2]{#3}
\IfValueTF{#4}{%
\textcolor{red}{You used the optional 2nd and 4th. arguments: }\textcolor{violet}{#4}%
}{%
\textcolor{blue}{You used the optional 2nd argument but omitted the optional 4th one}%
}
}{%
\origsection{#3}
\IfValueTF{#4}{%
\textcolor{red}{You used the optional 4th. argument: }\textcolor{violet}{#4}%
}{%
\textcolor{blue}{You omitted the optional argument}
}
}%
}%
}

\begin{document}
\tableofcontents

\section*{Starred section}[With an optional argument]
\section{A section}
\section[Another section]{Another section with useless long title}
\section[Another section]{Another section with useless long title}[And again with an optional argument]
\section{A section}[With optional arg]

\end{document}


If you really want the last be optional then use the TeX level for the new command:

\documentclass{article}
\makeatletter
\def\mysec#1#2{\@ifnextchar[{\mysec@i{#1}{#2}}{\mysec@i{#1}{#2}[]}}%
\def\mysec@i#1#2[#3]{%
\textbf{#1} \\ #2
\ifx\relax#3\relax \else \\ #3 \fi}% or whatever you want to do with #3
\makeatother
\begin{document}

\mysec{foo}{bar}

\mysec{foo}{bar}[baz]

\end{document}

• Thanks! But to me it's not important which argument is optional – Jamgreen Nov 22 '15 at 12:01
• then use the solution from David with my \ifx ... – user2478 Nov 22 '15 at 12:14
• @Jamgreen: And which argument do you want to be optional? – Werner Nov 22 '15 at 12:28