我正在尝试用逗号分隔的参数替换宏。
下面的代码可以正常工作:
\documentclass{article}
\usepackage{listings}
\lstset{
literate={->}{\texttt{->}}{2}
}
\begin{document}
\begin{lstlisting}
Example
\end{lstlisting}
\end{document}
由于\newcommand
只是生成一个将被替换的宏,我希望下面的代码也能正常工作。
\documentclass{article}
\usepackage{listings}
\newcommand{\somemacro}{{->}{\texttt{->}}{2}}
\lstset{
literate=\somemacro
}
\begin{document}
\begin{lstlisting}
Example
\end{lstlisting}
\end{document}
但它会导致多个错误。
那么,我的假设到底错在哪里,\newcommand
以及如何正确定义可以用作参数的宏?
答案1
这归结为扩展是一个问题。考虑一个稍微简单一点的类似示例:
\documentclass{article}
\newcommand{\someothermacro}[2]{.#1.#2.}
\newcommand{\someargument}{{first}{second}}
\begin{document}
\someothermacro\someargument
\end{document}
有人会认为调用\someothermacro\someargument
类似于\someothermacro{first}{second}
。直观上看,是的,但 TeX 会盲目地抓取参数(实际上是标记)。由于\someothermacro
需要 2 个参数,它会抓取\someargument
第一个参数并将\end
(从 开始)作为\end{document}
第二个参数,然后扩展为.{first}{second}.\end.
而不是.first.second.
。由于\end
没有与其开头(document
在本例中)相对应的适当环境名称,因此它会失败,并指出\begin{document}
由 结束\end{.}
。
你可以使用以下方法规避这个问题
\expandafter\someothermacro\someargument
这相当简单。但是,在您的设置中,扩展必须以不同的方式进行。更具体地说,使用\begingroup\edef\x{\endgroup ...}\x
是最简单的。
如果希望样式设置可见,可以使用以下扩展形式:
\usepackage{listings}
\newcommand{\somemacro}{{->}{\noexpand\texttt{->}}{2}}
\begingroup\edef\x{\endgroup\noexpand
\lstset{
literate=\somemacro
}}\x
“扩展代码”围绕着您的\lstset
构造,并要求任何敏感内容(不需要扩展的内容)以 为前缀\noexpand
。
定义一个style
使用方法可能会更好\lstdefinestyle{<style>}{<key value list>}
,这样可以隐藏一些细节,然后直接使用
\lstset{
style=<style>,
% other settings
}
在您的主文档中。