因此,我正在考虑创建一个以任何乳胶代码作为参数的宏。例如,
\newcommand\purp[1]{\color{purple} #1}
我希望这个宏能让 \purp 内的任何乳胶代码都变成紫色。但我意识到,如果我将某个环境(\begin.. \end)传递给参数,就会出现一些奇怪的乳胶错误。例如。
\purp{
\begin{verbatim}
asdfadf
asdf
asdf
\end{verbatim}
}
破坏逐字输出并生成一堆乳胶错误。有没有安全的方法来创建一个以任意乳胶代码作为参数的函数?
编辑
除了逐字逐句之外,我还观察到以下内容产生了非常奇怪的错误。
\purp{
\[
x= \begin{cases*}
y & if x_1 \text{ is } 1\\
z & if x_2 \text{ is } 2
\end{cases*}
\]
}
这会出现一个奇怪的错误:缺少 $ 插入。知道原因吗?
答案1
几乎通用的规则是verbatim
材料不能作为命令的参数。使用该cprotect
包,有时会出现如 MWE 中所示的解决方法,但即使这样也不是通用的解决方案。
编辑:添加组以防止紫色溢出到后续材料中(感谢 Ulrike)。
\documentclass{article}
\usepackage{cprotect,xcolor}
\newcommand\purp[1]{{\color{purple} #1}}
\begin{document}
\cprotect\purp{
\begin{verbatim}
asdfadf
asdf
asdf
\end{verbatim}
}
\end{document}
答案2
如果只是关于颜色,你可以伪造一个\textcolor
命令,它似乎接受一个参数,但确实支持逐字材料。请注意,这不是通用解决方案,而只是提供了一个参数,该参数采用的语法实际上\color
并不是参数。
(这样,人们可以使用任何格式开关,而不仅仅是颜色,例如\bfseries
也可以这样使用)
编辑:创建了一个\switchhack
允许任意格式切换的功能,不仅是颜色,而且现在还\colorhack
可以调用\switchhack
。
\documentclass[]{article}
\usepackage{xcolor}
\makeatletter
\begingroup\def\:#1{\endgroup\let\switchhack@sptoken= #1}\:{ }
\newcommand\switchhack[1]
{%
\def\switchhack@switch{#1}%
\switchhack@a
}
\newcommand\switchhack@a
{%
\futurelet\switchhack@gobbled\switchhack@b
}
\newcommand\switchhack@b
{%
\ifx\switchhack@gobbled\switchhack@sptoken
\switchhack@eatspace
\fi
\@firstofone
{%
\ifx\bgroup\switchhack@gobbled
\else
\GenericWarning
{}{Warning: Argument of \string\switchhack\space not delimited}%
\switchhack@undelimeted
\fi
\switchhack@delimited
}%
}
\long\def\switchhack@eatspace\fi#1#2%
{%
\fi
\afterassignment\switchhack@a
\let\switchhack@gobbled=
}
\long\def\switchhack@undelimeted\fi#1#2%
{%
\fi
{\switchhack@switch#2}%
}
\newcommand\switchhack@delimited
{%
\afterassignment\switchhack@do
\let\switchhack@gobbled
}
\newcommand\switchhack@do
{%
\bgroup\switchhack@switch
}
\long\def\colorhack#1#{\colorhack@{#1}}
\newcommand\colorhack@[2]
{%
\switchhack{\color#1{#2}}%
}
\makeatother
\newcommand\purp{\colorhack{purple}}
\newcommand\bfhack{\switchhack{\bfseries}}
\begin{document}
\colorhack[rgb]{.5 .4 .8}{foo}
\purp{\verb|this is blue|}
following text
\bfhack{this is bold}
\colorhack{red} Undelimeted
\purp{
\begin{verbatim}
This is
verbatim
purple (I lied up there, it never was blue)
\end{verbatim}
}
\end{document}
答案3
另一种获取以逐字材料为参数的宏的方法是将参数作为框来获取。同样,这不是通用的解决方案,您不能用它做任意的事情(最重要的是,在框化材料后,您无法更改其外观,这就是可选参数的用途grabbox
,以使某些格式成为可能)。
下面定义了\purp
将其参数放在 a 内部\hbox
以及\purp*
将其放在 a 内部\vbox
(当然两种情况下的宏名都是\purp
,第二个宏名后面只是加了一个星号)。
\documentclass[]{article}
\usepackage{grabbox}
\usepackage{xcolor}
\makeatletter
\newsavebox\purp@box
\newcommand\purp
{%
\begingroup
\@ifstar
{%
\grabbox\purp@box[\color{purple}]\vbox{\unvbox\purp@box\endgroup}%
}
{%
\grabbox\purp@box[\color{purple}]\hbox{\unhbox\purp@box\endgroup}%
}%
}
\makeatother
\begin{document}
\purp{\verb|this is blue|}
other text
\purp*{
\begin{verbatim}
This is
verbatim
purple (I lied up there, it never was blue)
\end{verbatim}
}
\end{document}