不一样的 LaTeX 教程:使用 listings 宏包美化代码

不一样的 LaTeX 教程:使用 listings 宏包美化代码

简介

LaTeX 中插入代码常用到 listings 宏包。利用 listing 宏包的相关设置可以大幅美化代码

获得更好的阅读体验,请关注微信公众号:极与客。

代码基础框架

  • 引入 listings 宏包。
  • 引入 xcolor 宏包,设置可选参数为 dvipsnames。
  • 在正文区使用 lstlisting 环境。
\documentclass{ctexart}
\usepackage{listings}
\usepackage[dvipsnames]{xcolor}
% 正文区
\begin{document}
% lstlisting环境
\begin{lstlisting}  % Python代码
import random
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDesk:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()
    
    def __init__(self):
        self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits]
        
    def __len__(self):
        return len(self._cards)
        
    def __getitem__(self, position):
        return self._cards[position]
desk = FrenchDesk()
\end{lstlisting}
\end{document}

编译结果


注意:以上结果中,代码超出该行时,直接被截断!

设置语言、基础字体族、自动换行

  • 可选参数 language 进行语言设置。
  • 可选参数 basicstyle = \ttfamliy ,设置为打字机字体族。
  • 可选参数 breaklines 进行自动换行。
\documentclass{ctexart}
\usepackage{listings}
\usepackage[dvipsnames]{xcolor}
% 正文区
\begin{document}
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true % 自动换行
]  
import random
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDesk:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()
    
    def __init__(self):
        self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits]
        
    def __len__(self):
        return len(self._cards)
        
    def __getitem__(self, position):
        return self._cards[position]
desk = FrenchDesk()
\end{lstlisting}
\end{document}

编译结果


设置语法高亮

1 设置关键字高亮

  • 指定语言后,会有一些默认的关键字。
  • 通过可选参数keywordstyle设置关键字样式。
  • 通过可选参数morekeywords指定更多的关键字。
注意:这里的更多关键字指的是那些在语言中属于关键字,但是没有被 LaTeX 识别。
\documentclass{ctexart}
\usepackage{listings}
\usepackage[dvipsnames]{xcolor}
% 正文区
\begin{document}
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={} % 设置更多的关键字,用逗号分隔
]  
import random
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDesk:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()
    
    def __init__(self):
        self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits]
        
    def __len__(self):
        return len(self._cards)
        
    def __getitem__(self, position):
        return self._cards[position]
desk = FrenchDesk()
\end{lstlisting}
\end{document}

编译结果

已经顺眼多了!

2 设置强调词高亮

  • 可选参数emph指定强调词。
  • 可选参数emphstyle设置强调词样式。
\documentclass{ctexart}
\usepackage{listings}
\usepackage[dvipsnames]{xcolor}
% 正文区
\begin{document}
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle={\bfseries\color{Rhodamine}} % 强调词样式设置
]  
import random
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
# 一个叫做 FrenchDesk 的类。a class named FrenchDesk.
class FrenchDesk:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()
    
    def __init__(self):
        self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits]
        
    def __len__(self):
        return len(self._cards)
        
    def __getitem__(self, position):
        return self._cards[position]
desk = FrenchDesk()
\end{lstlisting}
\end{document}

编译结果


悄悄地在 Python 代码中加了一些注释,但是好像并不美妙。

3 设置注释、字符串样式

  • 可选参数commentstyle设置注释样式。
  • 可选参数stringstyle设置字符串样式。
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black} % 设置字符串样式
]  
其他没有显示的代码不变。

编译结果


注释间距很奇怪,我们让它紧凑一些。

4 紧凑一些

  • 设置columns=flexible
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black}, % 设置字符串样式
    columns=flexible
]  

编译结果

注意:注释紧凑的同时,其他代码也紧凑了,但我觉得挺好。

显示行号

  • 设置可选参数numbers可显示行号,常numbers=left
  • 可选参数numbersep调整行号的具体位置。
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black}, % 设置字符串样式
    columns=flexible,
    numbers=left, % 显示行号在左边
    numbersep=2em % 设置行号的具体位置
]  

编译结果

太糟糕了!行号怎么这么大!
  • 通过设置可选参数numberstyle=\footnotesize使行号变小。
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black}, % 设置字符串样式
    columns=flexible,
    numbers=left, % 显示行号在左边
    numbersep=2em, % 设置行号的具体位置
    numberstyle=\footnotesize % 缩小行号
]  

编译结果

感觉很合适。

可以加个边框

  • 设置可选参数frame可以加一个边框,single表示单边框。
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black}, % 设置字符串样式
    columns=flexible,
    numbers=left, % 显示行号在左边
    numbersep=2em, % 设置行号的具体位置
    numberstyle=\footnotesize % 缩小行号
    frame=single % 边框
]  

编译结果

或许代码有点太靠边框了。
  • 可选参数framesep改变代码和边框的距离
注意:设置framesep移动是边框而非代码!
% lstlisting环境
\begin{lstlisting}[   % 进行参数设置
 language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black}, % 设置字符串样式
    columns=flexible,
    numbers=left, % 显示行号在左边
    numbersep=2em, % 设置行号的具体位置
    numberstyle=\footnotesize, % 缩小行号
    frame=single, % 边框
    framesep=1em % 设置边框与代码的距离
]  

编译结果


把设置移到导言区

  • LaTeX 结构与样式分离,需要避免在正文区进行大量的样式设置。
  • 在导言区,\setlst命令也可以完成对 lstlisting 环境的设置。
\documentclass{ctexart}
\usepackage{listings}
\usepackage[dvipsnames]{xcolor}
% 在导言区进行样式设置
\lstset{
    language=Python, % 设置语言
 basicstyle=\ttfamily, % 设置字体族
 breaklines=true, % 自动换行
 keywordstyle=\bfseries\color{NavyBlue}, % 设置关键字为粗体,颜色为 NavyBlue
 morekeywords={}, % 设置更多的关键字,用逗号分隔
 emph={self}, % 指定强调词,如果有多个,用逗号隔开
    emphstyle=\bfseries\color{Rhodamine}, % 强调词样式设置
    commentstyle=\itshape\color{black!50!white}, % 设置注释样式,斜体,浅灰色
    stringstyle=\bfseries\color{PineGreen!90!black}, % 设置字符串样式
    columns=flexible,
    numbers=left, % 显示行号在左边
    numbersep=2em, % 设置行号的具体位置
    numberstyle=\footnotesize, % 缩小行号
    frame=single, % 边框
    framesep=1em % 设置代码与边框的距离
}
% 正文区
\begin{document}
% lstlisting环境
\begin{lstlisting}
import random
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
# 一个叫做 FrenchDesk 的类。a class named FrenchDesk.
class FrenchDesk:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()
    
    def __init__(self):
        self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits]
        
    def __len__(self):
        return len(self._cards)
        
    def __getitem__(self, position):
        return self._cards[position]
desk = FrenchDesk()
\end{lstlisting}
\end{document}
这样也有另外一个好处,正文区的每一个 lstlisting 环境都会被设置上相应的样式。针对于特殊情况,我们也可以在特殊的 lstlisting 对相关属性进行重写。

结语

或许在运行本次例子时,你会感觉代码放在了中间并不宽敞的区域。那是因为默认的版心在中间很小的区域。你可以通过以下方法来设置版心为 A4 纸的 80%:

\usepackage{geometry}
\geometry{a4papter,scale=0.8}
本文的所有代码都悄悄地加了此设置。嘻嘻。

- END -

发布于 2022-02-05 17:05