13

What is the proper way to define a wrapper to a command which takes an optional argument (such as \chapter)? I mean a wrapper, not a clone, such that we can inject code into the wrapper without meddling with the command of which it is a wrapper.

This is how I do it. Is there a better way to do that? (I owe the conditional clause to egreg here.)

\documentclass{book}

\newcommand\mychapter[2][] {\if\relax\detokenize{#1}\relax
                             \chapter{#2}
                            \else
                             \chapter[#1]{#2}
                            \fi}

\begin{document}
\tableofcontents
\mychapter[Short title]{Long title}
\end{document}

let\mychapter\chapter will clone it, so that \mychapter won't be a wrapper to \chapter.

2
  • Perhaps I am missing something. Does \newcommand{\mychapter}{\chapter} do what you want? Commented Apr 27, 2015 at 16:00
  • Nope. This is not a wrapper. Suppose you want to do something else with either or both #1 and #2 in addition to passing them forward to \chapter. A wrapper would be able to do it, but your clone would not.
    – n.r.
    Commented Apr 27, 2015 at 16:04

2 Answers 2

11

Yes, there is a better way:

\usepackage{xparse}

\NewDocumentCommand{\mychapter}{som}{%
  %%% things to do before \chapter
  \IfBooleanTF{#1}
    {\chapter*{#3}}
    {\IfNoValueTF{#2}{\chapter{#3}}{\chapter[#2]{#3}}%
  %%% things to do after \chapter
}

This supports all three calls:

\mychapter*{Title}
\mychapter{Title}
\mychapter[Short title]{Long title}
7

The traditional way, before xparse allowed for more flexible solutions, is to use \@ifnextchar[ to check for the [ of the optional argument and to inject other code into the wrapper.

The starred version is included as well and can have an [] now as well -- it's up to the OP to decide what this [] should do then ;-)

\documentclass{book}



\newcommand\mychapter[2][]{\if\relax\detokenize{#1}%
                             \chapter{#2}
                            \else
                             \chapter[#1]{#2}
                            \fi}

\makeatletter
\newcommand{\myotherchapter@@opt}[2][]{%
  \chapter[#1]{#2}%
}

\newcommand{\myotherchapter@@noopt}[1]{%
  \chapter{#1}%
}

\newcommand{\myotherchapter@@starredopt}[2][]{%
  % Decide yourself what to do with #1 ;-)
  \chapter*{#2}
}


\newcommand{\myotherchapter@@starrednoopt}[1]{%
  \myotherchapter@@starredopt[#1]{#1}%
}

\newcommand{\myotherchapterstarred}{%
  \@ifnextchar[{\myotherchapter@@starredopt}{\myotherchapter@@starrednoopt}%
}

\newcommand{\myotherchapterunstarred}{%
  \@ifnextchar[{\myotherchapter@@opt}{\myotherchapter@@noopt}%
}

\newcommand{\myotherchapter}{%
  \@ifstar{\myotherchapterstarred}{\myotherchapterunstarred}%
}

\makeatother

\begin{document}

\tableofcontents

\mychapter[Short title]{Long title}

\myotherchapter{First}
\myotherchapter[Short Title]{Long title}

\myotherchapter*[Starred Short Title]{Starred Long title}

\myotherchapter*{Starred Long title}



\end{document}

You must log in to answer this question.

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