我的目标是能够lstlisting
通过转义到 LaTeX 并在转义部分中构建新字体来对环境中的任意文本选择进行字体更改(有没有比这种方法更聪明的方法来进行此类字体更改?)。但是,我希望能够在转义部分中维护逐字环境,即保留空格并且特殊字符不会引起问题。
换句话说,我想创建一个宏altfont
来执行如下操作:
\begin{lstlisting}[escapeinside={(*@}{@*)}]
Some text here and (*@\altfont{now a change in font}@*) and now back to
the regular font.
\end{lstlisting}
我的第一个想法是在转义部分中使用调用lstinline
,但不幸的是,根据listings
文档,这是不允许的。在此设置中使用verb
也会导致我在编译期间引发错误。
因此,我尝试创建自己的宏来完成以下示例所示的工作,但无法达到预期的效果。我遇到的一个问题是让宏尊重空格,第二个问题是某些特殊字符导致宏阻塞(例如字符%
)。
希望下面的例子可以进一步说明我正在做的事情。
\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
% sets the font for lstlisting environments to a monospace font, and sets an
% escape sequence that can be used to inject arbitrary LaTeX code into an
% lstlisting environment
\lstset{%
basicstyle=\fontfamily{pcr}\selectfont,
escapeinside={(*@}{@*)}
}
% create an alternative font to use for escaped sequences inside lstlisting
% environments
\newcommand{\altfont}[1]{%
\fontfamily{pcr}\selectfont{\color{blue}\obeyspaces\detokenize{#1}}
}
\begin{document}
% target spacing
\begin{lstlisting}
this text
is
properly
aligned
\end{lstlisting}
% using the contents of `altfont` handles spaces properly
\begin{lstlisting}
this text
is
(*@\fontfamily{pcr}\selectfont{\color{blue}\obeyspaces\detokenize{ also}}@*)
aligned
\end{lstlisting}
% the macro itself eats the spaces
\begin{lstlisting}
this text
is
(*@\altfont{ not}@*)
aligned
\end{lstlisting}
\end{document}
编译示例的输出:
答案1
当 TeX 首次读取空格并修复其 catcode 时,多个空格会被折叠。这种情况发生在调用宏时,在内容被评估之前,因为 TeX 必须读取参数。此时\obeyspaces
尚未评估,因此没有效果。
可以通过\obeyspaces
在参数扫描之前移动来解决这个问题,因此您可以\altfont
用
\newcommand{\altfont}{%
\begingroup%
\catcode`\\=12\relax%
\catcode`\%=12\relax%
\obeyspaces%
\expandafter\endgroup\altfontHelper%
}
\newcommand{\altfontHelper}[1]{%
{\fontfamily{pcr}\selectfont\color{blue}{}\detokenize{#1}}%
\endgroup%
}
这些\catcode
线条用于允许\
并%
以逐字的方式使用。
使用逐字参数定义命令变得更容易解析. 使用此包,您的文档将变成
\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{xparse}
% sets the font for lstlisting environments to a monospace font, and sets an
% escape sequence that can be used to inject arbitrary LaTeX code into an
% lstlisting environment
\lstset{%
basicstyle=\fontfamily{pcr}\selectfont,
escapeinside={(*@}{@*)}
}
% create an alternative font to use for escaped sequences inside lstlisting
% environments
\NewDocumentCommand\altfont{v}{%
{\fontfamily{pcr}\selectfont\color{blue}{}#1}
}
\begin{document}
% target spacing
\begin{lstlisting}
this text
is
properly
aligned
\end{lstlisting}
% using the contents of `altfont` handles spaces properly
\begin{lstlisting}
this text
is
(*@\fontfamily{pcr}\selectfont\obeyspaces\color{blue}{} also@*)
aligned
\end{lstlisting}
% the macro itself no longer eats the spaces
\begingroup\obeyspaces%
\begin{lstlisting}
this text
is
(*@\altfont{ now also}@*)
aligned
\end{lstlisting}
\endgroup%
\end{document}