我尝试自己定义一个宏,它根据输入变量输出不同的字符串(类似于其他编程语言中的 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 中有效,我们可以在宏定义之前或之后使用它。这无关紧要。