如何获得既具有长标识符换行功能又具有关键字突出显示的列表?

如何获得既具有长标识符换行功能又具有关键字突出显示的列表?

我目前正在写一本关于生物信息学的书,我想为读者提供一些有用的命令行来调用最新的软件。为此,我使用 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包将ACGTU视为“字母”(废话!);但是,您可以listings在字符串文字中交替将这五个字母本地视为“字母”和“其他”,以允许在它们之间换行。

下面显示的方法会自动换行由ACGT和组成的长字符串文字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\iffalseescape但失败了。

我只能为您提供手动破解的解决方案:

\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>。抱歉,但我也没有成功。

如果您没有那么多长字符串,那么像图中所示的那样将其断开可能就足够了。

相关内容