我目前正在写一本关于生物信息学的书,我想为读者提供一些有用的命令行来调用最新的软件。为此,我使用 listings 包来格式化最小的 python 脚本,这些脚本的执行将产生章节中的图表。
这个包总体上很好用,但我很难让它在长字符串上正确地换行,如下面的 MWA 所示,其中的字符串根本没有被打破。
\documentclass{minimal}
\usepackage{listings}
\lstloadlanguages{Python}
\lstset{
language=Python,
basicstyle=\ttfamily,
morekeywords={rna},
breaklines=true,
keywordstyle={\bfseries\color{purple}},
}
\begin{document}
\begin{lstlisting}[caption={No line breaking}]
rna = "ACUUGUAUAACCUCAAUAAUAUGGUUUGAGGGUGUCUACCAGGAACCGUAAAAUGGUGAUUACAAAAUUUGUUUAUGACAUUUUUUGUAAUCAGGAUUUUUUUU"
\end{lstlisting}
\end{document}
在Listings 包未破,给出了一个 Tex hack,将“字母”状态从每个字符中移除,从而允许 listings 包将长 id/字符串视为“原子标记”序列。新的 MWA 应为:
\documentclass{minimal}
\usepackage{listings}
\lstloadlanguages{Python}
\lstset{
language=Python,
basicstyle=\ttfamily,
morekeywords={rna},
breaklines=true,
keywordstyle={\bfseries\color{purple}},
}
\begin{document}
\makeatletter
\def\lst@lettertrue{\let\lst@ifletter\iffalse}
\makeatother
\begin{lstlisting}[caption={No line breaking}]
rna = "ACUUGUAUAACCUCAAUAAUAUGGUUUGAGGGUGUCUACCAGGAACCGUAAAAUGGUGAUUACAAAAUUUGUUUAUGACAUUUUUUGUAAUCAGGAUUUUUUUU"
\end{lstlisting}
\end{document}
但是,编译上述代码不再提供任何语法高亮,如下图所示(红线代表边距的边缘):
是否可以同时实现长 ID/字符串的换行,而不会丢失语法高亮?
答案1
linebreak
当设置了option但未breakatwhitespace
设置 option 时,listings
允许在被视为“其他”的字符处换行。默认情况下,该listings
包将A
、C
、G
、T
和U
视为“字母”(废话!);但是,您可以listings
在字符串文字中交替将这五个字母本地视为“字母”和“其他”,以允许在它们之间换行。
下面显示的方法会自动换行由A
、C
、G
、T
和组成的长字符串文字U
,并且不会影响标识符(关键字等)的语法高亮显示。
\documentclass{article}
\usepackage[showframe]{geometry} % only to make page layout visible
% and check that everything is OK
\usepackage[dvipsnames]{xcolor}
\usepackage{listings}
% ----- some listings tweaks ---
\makeatletter
\newif\ifinstring@rna@ %
\newif\iflastACGTUwasother@rna@ % switch to keep track of whether the last
% base typeset was treated by listings as
% "letter" or "other"
% we redefine the stringstyle key for convenience
\lst@Key{stringstyle}{}{\def\lst@stringstyle{\global\instring@rna@true#1}}
% new language definition for allowing for linebreaks in long DNA/RNA chains
\lstdefinelanguage{PythonRNA}%
{
language = Python,
morekeywords = {rna,True},% possibly other keywords...
breaklines = true,
breakatwhitespace = false,
SelectCharTable =
\ProcessOtherOrLetter@rna{A}\rna@A
\ProcessOtherOrLetter@rna{C}\rna@C
\ProcessOtherOrLetter@rna{G}\rna@G
\ProcessOtherOrLetter@rna{T}\dna@T
\ProcessOtherOrLetter@rna{U}\rna@U
}
% helper macro that alternately treats bases as "letter" or "other" in order
% to allow for linebreaks between them
\newcommand\ProcessOtherOrLetter@rna[2]
{%
\lst@DefSaveDef{`#1}#2%
{%
\ifinstring@rna@%
\iflastACGTUwasother@rna@%
\lst@ProcessLetter #1%
\global\lastACGTUwasother@rna@false%
\else
\lst@ProcessOther #1%
\global\lastACGTUwasother@rna@true%
\fi
\else
#2%
\fi
}%
}
\lst@AddToHook{EndGroup}{\global\instring@rna@false}
\makeatother
% ----- END of listings tweaks ---
% ----- user style customisation ---
\lstdefinestyle{myPythonRNAstyle}
{
language = PythonRNA,
stringstyle = \color{blue},
keywordstyle = \bfseries\color{purple},
basicstyle = \ttfamily,
emph = {Uuu}, % sanity check
emphstyle = \color{ForestGreen},
}
\lstset{style=myPythonRNAstyle}
\begin{document}
\begin{lstlisting}[caption={Automatic line breaking}]
rna = "ACUUGUAUAACCUCAAUAAUAUGGUUUGAGGGUGUCUACCAGGAACCGUAAAAUGGUGAUUACAAAAUUUGUUUAUGACAUUUUUUGUAAUCAGGAUUUUUUUU"
# check that identifiers are still recognised
True Uuu
\end{lstlisting}
\end{document}
答案2
这取决于您希望它看起来像什么。到目前为止,您的第二个带有彩色“rna”的示例对我来说不起作用。我尝试在长字符串的前面和后面设置 with \def\lst@lettertrue{\let\lst@ifletter\iffalse
,escape
但失败了。
我只能为您提供手动破解的解决方案:
\documentclass{minimal}
\usepackage{xcolor}
\usepackage{listings}
\lstloadlanguages{Python}
\lstset{
language=Python,
basicstyle=\ttfamily,
morekeywords={rna},
breaklines=true,
breakatwhitespace=false,
keywordstyle={\bfseries\color{purple}},
escapeinside={(*@}{@*)},
}
\begin{document}
\begin{lstlisting}[caption={No line breaking}]
rna ="ACUUGUAUAACCUCAAUAAUAUGGUUUGAGGGUGUCUACCAGGAACCGUAAAAUGGUGAUUACAA(*@@*)AAUUUGUUUAUGACAUUUUUUGUAAUCAGGAUUUUUUUU"
rna ="ACUUGUAUAACCUCAAUAAUAUGGUUUGAGGGUGUCUACCAGGAACCGUAAAAUGGUGAUUACA AAAUUUGUUUAUGACAUUUUUUGUAAUCAGGAUUUUUUUU"
\end{lstlisting}
\end{document}
如果您希望将断线标记为这样,您应该查看prebreak=<token>
。抱歉,但我也没有成功。
如果您没有那么多长字符串,那么像图中所示的那样将其断开可能就足够了。