我用它listings
来高亮显示 ruby 代码。我有以下测试文档:
\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{mauve}{rgb}{0.58,0,0.82}
\lstdefinestyle{Ruby} {
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle={\footnotesize\ttfamily},
numberstyle={\tiny},
numbers=left,
keywordstyle=\color{blue},
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
breaklines=true,
breakatwhitespace=true,
tabsize=2,
sensitive = true
}
\lstset{language=Ruby}
\begin{document}
\begin{lstlisting}[style=Ruby,float=ht,caption={...},label={lst:sourcecode},captionpos=b]
def some_function
File.open(filename, 'w+') do |f|
[...]
# a comment
f.puts "whatever #{some_variable} another string part"
f.puts 'this string contains apostrophes: \'random word\''
[...]
end
end
\end{lstlisting}
\end{document}
看起来像这样:
当然,#{some_variable}
由于我将其设置为字符串样式,因此以紫色/淡紫色突出显示,但这并不完全正确,因为语法#{}
将执行内容而不是将该块解释为字符串(仅当在内部时" "
,而不是在' '
,但我愿意忽略这种微妙之处)。
我的问题是,有没有办法配置突出显示以正确表示这一点,以便#{some_variable}
具有默认颜色?
编辑:根据 SDF 给出的答案,它现在看起来像这样:
如果比较这两张图片,您会发现现在周围的转义撇号random word
不会像以前那样被忽略(这是正确的行为)。
编辑 2:虽然我可以通过省略来解决这个问题string=[d]{'},
,但我注意到另外两个问题。示例现在如下所示:
\documentclass{article}
\usepackage{xcolor}
\usepackage[procnames]{listings}
\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{gray}{rgb}{0.5,0.5,0.5}
\definecolor{mauve}{rgb}{0.58,0,0.82}
\definecolor{light-gray}{gray}{0.25}
\lstdefinestyle{Ruby} {
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle={\footnotesize\ttfamily},
numberstyle={\tiny},
numbers=left,
keywordstyle=\color{blue},
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
breaklines=true,
breakatwhitespace=true,
tabsize=2,
sensitive = true,
morestring=*[d]{"},
morestring=[s][]{\#\{}{\}},
procnamekeys={def},
procnamestyle=\color{red},
}
\lstset{language=Ruby}
\begin{document}
\begin{lstlisting}[style=Ruby,float=ht,caption={...},label={lst:sourcecode},captionpos=b]
def some_function
File.open(filename, 'w+') do |f|
[...]
# a comment
f.puts "whatever #{some_variable} another string part"
f.puts 'this string contains apostrophes: \'random word\''
f.puts 'i do love keywords like class'
f.puts "i do love keywords like class"
f.puts "now single quotes 'inside #{double quotes}'"
[...]
end
end
\end{lstlisting}
\end{document}
双引号内的关键字现在被突出显示,并且双引号内的单引号也导致原始问题再次出现。
这件事慢慢地变得无法控制了...也许我真的应该改用 minted。
答案1
笔记:
我更新了整个答案以考虑这两项修改。有很多小技巧,但我担心我们想要使用的越精确listings
,我们需要添加的技巧就越多。请参阅答案末尾的替代解决方案minted
。
使用以下方法解决初始问题listings
您可以通过在其定义中listings
添加来检测另一个分隔符内的分隔符:*
morestring=*[d]{"}
然后我们定义#{
和}
作为特殊分隔符。我们通过添加第二对方括号赋予它们自己的样式:
morestring=[s][]{\#\{}{\}}
这里我们添加了空括号,这意味着将使用默认样式。另外,不要忘记转义特殊字符,例如#
、{
等。有关更详细的解释,请参阅listings
文档第 3.3 节。
评论:
s
选项意味着开始和结束分隔符不同,d
它们是相同的。必须使用b
而不是d
启用反斜杠转义。我在最初的回答中犯了这个错误。还值得注意的是,Ruby 与大多数语言一样,已经有一个基本定义,其中包括大多数字符串,因此无需重新定义所有内容(除非我们想覆盖它,我们会这样做)。
这是\lstset
产生 OP 第一次编辑中所见的输出:
\lstdefinestyle{Ruby} {
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle={\footnotesize\ttfamily},
numberstyle={\tiny},
numbers=left,
keywordstyle=\color{blue},
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
breaklines=true,
breakatwhitespace=true,
tabsize=2,
morestring=[d]{'}, % wrong: should be [b]
morestring=*[d]{"},
morestring=[s][]{\#\{}{\}},
}
解决其他问题
字符串内的关键字被突出显示
正如 Daniel 在评论中所说,中的星星morestring=*[d]{"}
使它能够进一步寻找更多的琴弦和关键字。这就是我们想要的关于“ #{
-}
字符串”的内容,但它也发生在关键字上。
listings
不允许指定我们在字符串中究竟要寻找什么,所以我们必须找到另一种解决方法。
现在,listings
提供一个**
选项,以便字符串的样式及其特殊内容可以累积。例如,当我们这样做时:
morestring=**[d][\color{mauve}]{"},
keywordstyle=\bfseries,
listings
将使双引号内的关键字都变为粗体和淡紫色。问题是,我们需要“累积”颜色。
morestring=**[d][\color{mauve}]{"},
keywordstyle=\color{blue},
在这种情况下,字符串内的关键字将使用 进行处理\color{mauve} \color{blue}
,这很糟糕:关键字样式会覆盖字符串样式。我的窍门是用一个新命令替换关键字样式,该命令检查当前颜色,如果颜色不是淡紫色,则将其设置为蓝色:
\def\bluecolorifnotalreadymauve{%
\extractcolorspec{.}\currentcolor
\extractcolorspec{mauve}\stringcolor
\ifx\currentcolor\stringcolor\else
\color{blue}%
\fi
}
(谢谢这个答案寻找解决方案。
现在我们也失去了原来的修复,因为它的(空)样式与from#{}
一起“累积” 。让我们把它累积回来:\color{mauve}
""
morestring=[s][\color{black}]{\#\{}{\}},
单引号导致#{}
问题再次出现
就像关键字一样,单引号字符串在双引号字符串内重新处理。并且listings
没有被告知要查看单引号字符串内部,所以我们必须以相同的方式更改它们:
morestring=**[d]{'},
现在我们失去了反斜杠转义。由于未知原因,b
选项与 配合不好**
。好吧,既然我们这样做了……
morestring=[d]{\\'},
完全更新的 MWE
\documentclass{article}
\usepackage{xcolor}
\usepackage[procnames]{listings}
\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{gray}{rgb}{0.5,0.5,0.5}
\definecolor{mauve}{rgb}{0.58,0,0.82}
\definecolor{light-gray}{gray}{0.25}
\def\bluecolorifnotalreadymauve{%
\extractcolorspec{.}\currentcolor
\extractcolorspec{mauve}\stringcolor
\ifx\currentcolor\stringcolor\else
\color{blue}%
\fi
}
\lstdefinestyle{Ruby} {
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle=\footnotesize\ttfamily,
numberstyle=\tiny,
numbers=left,
keywordstyle=\bluecolorifnotalreadymauve,
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
breaklines=true,
breakatwhitespace=true,
tabsize=2,
moredelim=[s][\color{black}]{\#\{}{\}}, % same as morestring in this case
morestring=**[d]{'},
morestring=[d]{\\'},
morestring=**[d]{"},
procnamekeys={def}, % bonus, for function names
procnamestyle=\color{red},
}
\lstset{language=Ruby}
\begin{document}
\begin{lstlisting}[style=Ruby,float=ht,caption={...},label={lst:sourcecode},captionpos=b]
def some_function
File.open(filename, 'w+') do |f|
[...]
# a comment
f.puts "whatever #{some_variable} another string part"
f.puts 'this string contains apostrophes: \'random word\''
f.puts 'i do love keywords like class'
f.puts "i do love keywords like class"
f.puts "now single quotes 'inside #{double quotes}'"
[...]
end
end
\end{lstlisting}
\end{document}
输出:
替代方法:使用minted
minted
已经满足了你的所有要求,甚至更多!以下是 MWE:
\documentclass{article}
\usepackage{minted}
\begin{document}
\begin{listing}[H]
\begin{minted}[fontsize=\footnotesize, linenos]{Ruby}
def some_function
File.open(filename, 'w+') do |f|
[...]
# a comment
f.puts "whatever #{some_variable} another string part"
f.puts 'this string contains apostrophes: \'random word\''
f.puts 'i do love keywords like class'
f.puts "i do love keywords like class"
f.puts "now single quotes 'inside #{double quotes}'"
[...]
end
end
\end{minted}
\caption{...}
\end{listing}
\end{document}
这是具有默认样式的输出:
的主要缺点minted
是它依赖于皮格门特斯进行处理,这意味着:
安装可能有点棘手。
它很难定制。(但是一旦我们知道如何定制,它就会变得非常强大。)