我用來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}
以紫色/紫紅色突出顯示,因為我將其設為字串樣式,但這並不是真正正確的,因為語法#{}
將執行內容而不是將此區塊解釋為字串(僅當 inside " "
,而不是 with ' '
,但我會願意忽略這種微妙之處)。
我的問題是,有沒有辦法配置突出顯示以正確表示這一點,以便#{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}
雙引號內的關鍵字現在被反白顯示,雙引號內的單引號也會導致原來的問題再次出現。
這正在慢慢失去控制......也許我真的應該改用鑄幣。
答案1
筆記:
我更新了整個答案以考慮這兩個編輯。有很多小技巧,但恐怕我們想要使用的越精確listings
,我們需要添加的技巧就越多。請參閱答案末尾的替代解決方案,使用minted
.
使用解決最初的問題listings
您可以透過在定義中listings
新增 a 來允許偵測另一個分隔符號內的分隔符號:*
morestring=*[d]{"}
然後我們將#{
and定義}
為特殊分隔符號。我們透過添加第二個對方括號來賦予它們自己的風格:
morestring=[s][]{\#\{}{\}}
在這裡,我們添加空括號,這意味著將使用預設樣式。另外,不要忘記轉義特殊字符,例如#
、{
等。listings
評論:
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][]{\#\{}{\}},
}
解決其他問題
字串內的關鍵字突出顯示
正如丹尼爾在評論中所說,星號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
}
(謝謝這個答案以獲得解決方案。
現在我們也失去了原來的#{}
修復,因為它的(空)樣式是與\color{mauve}
from一起「累積」的""
。讓我們把它累積回來:
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
是它依賴於皮格門斯進行處理,這意味著:
安裝起來可能有點棘手。
客製化更難。 (但是一旦我們知道如何做,它就會非常強大。)