4

I have made a command

\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.

Jamgreen
  • 3,687
  • 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

3 Answers3

11

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}
David Carlisle
  • 757,742
  • 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
  • 2
    @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
2

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}
1

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}