我想突出显示软件包显示的 C 文件注释中的单个单词(或短语)listings
。使用emph
键在注释中不起作用(listings
如果设置了语言,则显然太智能了):注释中的单词(和字符串文字)似乎没有被考虑 - 只有普通代码中的(关键)单词才会被考虑。
基于literate
以下选项的解决方法这个答案如下所示。
我正在寻找一种无需修改实际源代码即可工作的解决方案,并且它lstinputlisting
也应该可以工作。
\documentclass{article}
\usepackage{listings,xcolor}
\lstset{
language=C,
}
\begin{document}
% \begin{lstlisting}[emph={Hello},emphstyle=\underbar]
\begin{lstlisting}[literate={Hello}{{{\color{red}Hello}}}5]
/*
* Hello World Program
*/
// Hello
#include <stdio.h>
int main (void) {
printf("Hello World!\n");
int Hello = 0;
int hello = 0;
return Hello;
}
\end{lstlisting}
\end{document}
该解决方法的主要问题是匹配字符的间距。
答案1
您的文本中的问题literate
是替换文本中的多余括号。
literate
当解析密钥的第二个参数时,每个 LaTeX 标记或{...}
-group——我们称之为物品— 被视为替换输出中的一个字符。因此,{{\color{red}Hello}}
被解析为单个项目并导致错误的间距。5
最后的 仅告诉它假设整体替换文本的宽度为单个字符宽度的 5 倍。
因此解决方案是将替换文本分成 5 个(可打印)项目:
{\unskip\bgroup\color{red}}Hello{\unskip\egroup}
请注意,现在第一个和最后一个项目也被视为输出字符。由于\bgroup\color{red}
和\egroup
部分不可打印,因此输出中没有为它们占用空间。但是,listings
在每个项目前插入一个额外的粘连,必须将其删除\unskip
才能获得正确的整体间距。
请参见以下示例的输出差异:
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.c}
/*
* Hello World Program
*/
// Hello
#include <stdio.h>
int main (void) {
printf("Hello World!\n");
int Hello = 0;
int hello = 0;
return Hello;
}
\end{filecontents*}
\usepackage{listings,xcolor}
\lstset{
language=C,
}
\begin{document}
\lstinputlisting[literate={Hello}{{{\color{red}Hello}}}5]{\jobname.c}
\lstinputlisting[literate={Hello}{{\unskip\bgroup\color{red}}Hello{\unskip\egroup}}5]{\jobname.c}
\end{document}
我想补充说明为什么该emph
版本不起作用。listings
有不同的方式来定义输入文本的新分隔部分。您的示例中相关的是morecomment
和morestring
键。它们每个都有无星号 ( morecomment=
) 和有星号 ( morecomment=*
) 版本。
使用前一个版本时,不会扫描分隔符之间的文本以查找其他类别,例如关键字或强调词。但是,对于带星号的版本,会扫描文本以查找其他类别,并应用适当的样式。在预定义语言风格这些分隔的类别被定义为无星号版本。因此,如果您想要其中的文本替换,则必须将它们重新定义为带星号的版本。
请注意,似乎无法在应用的类样式和未在分隔环境中应用的类样式之间进行选择。为了解决关键字在注释或字符串中也被突出显示的不良副作用,我们可以在应用关键字样式之前保存当前活动的样式,并仅在特殊分隔环境之外应用它:
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.c}
/*
* Hello World Program
*/
// Hello
#include <stdio.h>
int main (void) {
printf("Hello World!\n");
int Hello = 0;
int hello = 0;
World greetings;
return Hello;
}
\end{filecontents*}
\usepackage{listings,xcolor}
\makeatletter
\lstset{
language=C,
emph={Hello},
emphstyle=\emphstyle,
morekeywords={World},
keywordstyle=\keywordstyle,
morecomment=*[l][\special@on\color{gray}\itshape]{//},
morecomment=*[s][\special@on\color{gray}\itshape]{/*}{*/},
morestring=*[b][\special@on\color{green}]",
}
\newif\ifspecial@env@
\def\special@on{\global\special@env@true}
\def\special@off{\global\special@env@false}
\lst@AddToHook{DetectKeywords}{%
\global\let\last@lst@thestyle=\lst@thestyle
}
\def\emphstyle{%
\last@lst@thestyle
\aftergroup\special@off
\underbar
}
\def\keywordstyle{%
\ifspecial@env@
\last@lst@thestyle
\else
\color{blue}%
\fi
\aftergroup\special@off
}
\makeatother
\begin{document}
\lstinputlisting{\jobname.c}
\end{document}
这里,World
关键字仅在注释和字符串之外时才突出显示,而强调单词的下划线样式则Hello
在任何地方应用。