4

I tried to define a macro myself, which outputs different strings according to the input variable (like select-case statements in other programming languages).

The problem:

If I use the code in headings, captions, etc., I get error messages and no pdf, unless I put a \protect before the macro (see example below).

I'd like to avoid that - can I redefine the macro to make it "robust" also in such environments?

Example file

\documentclass[11pt, a4paper]{scrbook}

\usepackage{color}
\usepackage{xstring}

\newcommand{\ed}[1]{% source: http://tex.stackexchange.com/q/64131/4009, needs package xstring
\textcolor{magenta}{
\,\bfseries\itshape\IfStrEqCase{#1}{{1}{A}
    {8}{B}
    {5}{C}
{3}{D}
{7}{E}
{11}{F}
{14}{G}
{16}{H}
{19}{J}}
    [??]
}} 

\listfiles

\begin{document}


1 \ed{1}

2 \ed{2}

3 \ed{3}

4 \ed{4} 

test

\section{in headings it does not work like \ed{11}, at leat in the main document}



\end{document}
2
  • 1
    \DeclareRobustCommand perhaps? ;-)
    – user31729
    Commented Mar 16, 2015 at 16:11
  • 1
    See tex.stackexchange.com/questions/61503/… for a discussion on \newcommand vs. \DeclareRobustCommand.
    – user31729
    Commented Mar 16, 2015 at 16:16

2 Answers 2

7

\DeclareRobustCommand can be used for such cases, however, there are expansion issues (i.e. it's not expandible).

The code uses the original version and a \DeclareRobustCommand version.

In addition one could use

  • \newrobustcmd from etoolbox package
  • \NewDocumentCommand from xparse package

\documentclass[11pt, a4paper]{scrbook}

\usepackage{etoolbox}
\usepackage{xparse}

\usepackage{color}
\usepackage{xstring}

\newcommand{\ed}[1]{% source: http://tex.stackexchange.com/q/64131/4009, needs package xstring
\textcolor{magenta}{
\,\bfseries\itshape\IfStrEqCase{#1}{{1}{A}
    {8}{B}
    {5}{C}
{3}{D}
{7}{E}
{11}{F}
{14}{G}
{16}{H}
{19}{J}}
    [??]
}} 

\newrobustcmd{\edetoolbox}[1]{% source: http://tex.stackexchange.com/q/64131/4009, needs package xstring
\textcolor{magenta}{
\,\bfseries\itshape\IfStrEqCase{#1}{{1}{A}
    {8}{B}
    {5}{C}
{3}{D}
{7}{E}
{11}{F}
{14}{G}
{16}{H}
{19}{J}}
    [??]
}} 


\NewDocumentCommand{\edxparse}{m}{% source: http://tex.stackexchange.com/q/64131/4009, needs package xstring
\textcolor{magenta}{
\,\bfseries\itshape\IfStrEqCase{#1}{{1}{A}
    {8}{B}
    {5}{C}
{3}{D}
{7}{E}
{11}{F}
{14}{G}
{16}{H}
{19}{J}}
    [??]
}} 




\DeclareRobustCommand{\edother}[1]{% source: http://tex.stackexchange.com/q/64131/4009, needs package xstring
\textcolor{magenta}{
\,\bfseries\itshape\IfStrEqCase{#1}{{1}{A}
    {8}{B}
    {5}{C}
{3}{D}
{7}{E}
{11}{F}
{14}{G}
{16}{H}
{19}{J}}
    [??]
}} 


\listfiles

\begin{document}


1 \ed{1}

2 \ed{2}

3 \ed{3}

4 \ed{4} 

test

\section{in headings it does not work like \protect\ed{11}, at leat in the main document}

\section{in headings it does not work like \edother{11}, at leat in the main document}

\section{in headings it does not work like \edetoolbox{11}, at leat in the main document}

\section{in headings it does not work like \edxparse{11}, at leat in the main document}



\end{document}
2
  • There's also \robustify from etoolbox.
    – Manuel
    Commented Mar 17, 2015 at 10:36
  • @Manuel: I know, but I never used it so far. Thanks
    – user31729
    Commented Mar 17, 2015 at 12:59
2

When we are using plain TeX then we have two ways how to protect the macro. First one is possible by eTeX extension (commonly used). Instead of \def\macro we must say

\protected\def\macro 

This technique is possible in LaTeX too.

The second more comfortable way is available when OPmac macro package is used. We can say

\addprotect\macro 

which registers the control sequence \macro as protected. We needn't to change the definition of the \macro itself. The \addprotect declaration from OPmac works in classical TeX and we can use it before definition of the macro or after it. This doesn't matter.

You must log in to answer this question.

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