问题:

问题:

我尝试自己定义一个宏,它根据输入变量输出不同的字符串(类似于其他编程语言中的 select-case 语句)。

问题:

如果我在标题、说明等中使用代码,我会收到错误消息并且没有 pdf,除非我在\protect宏前面放置一个(见下面的示例)。

我想避免这种情况 - 我可以重新定义宏以使其在这样的环境中也“健壮”吗?

示例文件

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

答案1

\DeclareRobustCommand可以用于这种情况,但是存在扩展问题(即不可扩展)。

代码用的是原版和一个\DeclareRobustCommand版本。

此外,还可以使用

  • \newrobustcmd来自etoolbox
  • \NewDocumentCommand来自xparse

\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

当我们使用纯 TeX 时,我们有两种方法可以保护宏。第一种方法是通过 eTeX 扩展(常用)。\def\macro我们必须说

\protected\def\macro 

这种技术在 LaTeX 中也是可行的。

第二种更方便的方式是使用 OPmac 宏包。我们可以这样写

\addprotect\macro 

将控制序列注册\macro为受保护的。我们不需要更改其\macro本身的定义。OPmac\addprotect中的声明在经典 TeX 中有效,我们可以在宏定义之前或之后使用它。这无关紧要。

相关内容