我使用该listings
包在我的文档中排版代码。我定义了一个新环境,在\lstnewenvironment
其中\lstset
通过键值列表设置大量选项。它如下所示:
\lstnewenvironment{mycodebox}[1][]
{
\lstset{
key1=val1,
key2=val2,
% some more options are set
#1 % so that it can accept more options
}
}{}
我主要在两个变体中使用这个新环境,每个变体中我都需要覆盖一些现有(或添加新)选项。例如:
% variant 1
\begin{mycodebox}[newkey=newval, key1=newval]
% my code
\end{mycodebox}
和
% variant 2
\begin{mycodebox}[anotherkey=newval, key2=newval]
% my code
\end{mycodebox}
这两个变体有很多共同的选项,但它们是不同的。我可以定义两个宏/命令,例如和\variant1settings
,\variant2settigns
并可以像下面这样以某种方式使用吗?
\begin{mycodebox}[\variant1settings]
% my code
\end{mycodebox}
我知道\lstset{options...}
每次使用环境之前我都可以这样做,但是
- 当我没有在后续实例之前指定这些选项时,我不希望这些选项运行完毕;
- 我希望选项采用宏(或类似的)形式,以便可以从一个中心位置进行调整。
答案1
可选参数 #1 的内容的扩展必须推迟,否则宏\optionstocodebox
将被扩展,让keyval
宏认为其内容是一个完整的键名,当然事实并非如此。
使用
\begingroup\edef\x{\endgroup\noexpand\lstset{numbers=right,language={C},#1}}\x
将防止过早扩张,随后再进行扩张。
\begingroup...\endgroup
是一个巧妙的技巧,让重新定义\x
在扩展后被遗忘(这是}}\x
。
简而言之:首先阻止 \lstset 的扩展,然后通过调用来应用\x
。
然而,没有不可扩展的东西,例如\textbf
\textcolor
然而,没有微调就不允许使用或 之类的不可扩展的东西。这可以通过蛮力 \unexpanded{stuff}
作为键分配。第二个示例\otheroptionstocodebox
显示了方法的用法\unexpanded
。
\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\lstnewenvironment{mycodebox}[1][]
{
\begingroup\edef\x{\endgroup\noexpand\lstset{numbers=right,language={C},#1}}\x
}{}
\begin{document}
\newcommand{\optionstocodebox}{language={Pascal},numbers=left}%
\newcommand{\otheroptionstocodebox}{language={C},numbers=left,stepnumber=3,numberstyle={\unexpanded{\color{red}\tiny}}}%
\begin{mycodebox}[language={C}]
#include<stdio.h>
int main(int argc,char **argv)
{
printf("Hello World!\n");
}
\end{mycodebox}
\begin{mycodebox}[numbers=left,\optionstocodebox]
program first
BEGIN
WriteLn('Hello World');
END.
\end{mycodebox}
\begin{mycodebox}[language={C},\otheroptionstocodebox]
#include<stdio.h>
int main(int argc,char **argv)
{
printf("Hello World!\n");
}
\end{mycodebox}
\end{document}
答案2
listings
允许您定义可应用于单个列表的样式style=<stylename>
。
\documentclass{article}
\usepackage{listings,xcolor}
\lstdefinestyle{style1}{basicstyle=\ttfamily\color{red}}
\lstdefinestyle{style2}{basicstyle=\scshape\color{blue},frame=single}
\lstnewenvironment{mycodebox}[1][]
{
\lstset{
basicstyle=\itshape,
#1
}
}{}
\begin{document}
\begin{mycodebox}[style=style1]
This is some text
\end{mycodebox}
\begin{mycodebox}
This is some text
\end{mycodebox}
\begin{mycodebox}[style=style2]
This is some text
\end{mycodebox}
\end{document}