LaTeX中Python代码的语法高亮
本文中,“{}”中的字母为LaTeX或Python的包名,只有“Pygments”是Python的包,其余都是LaTeX的包。html
LaTeX提供了功能丰富的包(package),以实现某些特定的排版功能。其中,{listings}包和{minted}包主要用于文档中程序代码语法的高亮显示,支持常见的编程语言。python
- {listings}基于内置或用户提供的关键字高亮程序代码语法,高亮的内容受限于关键词的数量,代码的着色功能也是有限。
- {minted}使用Pymgent高亮程序代码,提供了更多的高亮内容,基本相似在Jupyter Notebook或Jupyter Qtconsole中的代码高亮。
使用{listings}包
{listings}的使用简洁明了:shell
- 在导言区加载包,并设置包选项。
- 在文档区使用
\begin{lstlisting}\end{lstlisting}
包围代码。 - 编译文档,PDF文件中,代码高亮显示。
能够根据本身的须要,经过\lstset
设置列表参数,或定义本身的列表新环境。若是没有特殊的需求,使用{listings}已经足够。以下使用{listings}高亮Python代码。编程
例 1
% !TeX program = xelatex \documentclass{ctexart} \usepackage{xcolor} %高亮使用的颜色 \definecolor{commentcolor}{RGB}{85,139,78} \definecolor{stringcolor}{RGB}{206,145,108} \definecolor{keywordcolor}{RGB}{34,34,250} \definecolor{backcolor}{RGB}{220,220,220} \usepackage{accsupp} \newcommand{\emptyaccsupp}[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} \usepackage{listings} \lstset{ %高亮代码设置 language=python, %Python语法高亮 linewidth=0.9\linewidth, %列表list宽度 %basicstyle=\ttfamily, %tt没法显示空格 commentstyle=\color{commentcolor}, %注释颜色 keywordstyle=\color{keywordcolor}, %关键词颜色 stringstyle=\color{stringcolor}, %字符串颜色 %showspaces=true, %显示空格 numbers=left, %行数显示在左侧 numberstyle=\tiny\emptyaccsupp, %行数数字格式 numbersep=5pt, %数字间隔 frame=single, %加框 framerule=0pt, %不划线 escapeinside=@@, %逃逸标志 emptylines=1, % xleftmargin=3em, %list左边距 backgroundcolor=\color{backcolor}, %列表背景色 tabsize=4, %制表符长度为4个字符 gobble=4 %忽略每行代码前4个字符 } \begin{document} 这是Python语法高亮 \begin{lstlisting} def prtmotto(n): for i in range(0,n): print("lift is short, i use Python!") \end{lstlisting} \end{document} }
使用{minted}包
{minted}包使用Python库(包)Pygments进行语法着色,因此首先必须安装Python,并安装Pygments库,同时使Python处于Windows系统路径。编程语言
{minted}的代码语法着色十分具备吸引力,但它没有{listings}好使用——简单的直接使用例外。当要在一个环境中包含minted环境,常常会带来许多问题。若是要定义本身的minted环境,比较方便的形式是使用{tcolorbox}包。ide
{mdframed}和{tcolorbox}都是定制框(box)的包,前者要本身hacker,后者的已有功能十分丰富,且定制功能强大。{tcolorbox}提供了minted
库,经过以下形式之一使用:函数
\usepackage[minted]{tcolorbox}
。自动加载{minted}包- 经过
\tcbuselibrary
加载\usepackage{tcolorbox} \tcbuselibrary{minted} %加载{minted}包
若是要定义新环境或命令,{tcolorbox}提供了以下命令:测试
\tcbset
设置全部tcolorbox的参数。tcolorbox
和tcblisting
环境创建box或列表list。\newtcblisting
或\newtcbinputlisting
建立新的列表环境(tcblisting)或宏。\newtcolorbox
或\newtcbox
建立新的tcolorbox环境或宏。\DeclareTCBListing
或\NewTCBListing
建立有一个可选参数的列表(仍是要2个以上的参数)。须要加载{xparse,listings},可是{minted}应该在{listings}的后面,不然会覆盖minted选项的设置。\usepackage[xparse,listings,minted]{tcolorbox} 或 \tcbuselibrary{xparse,listings,minted}
- 加载{xparse}后,选项中能够使用逻辑选项(对应xparse中的宏):
IfNoValueTF
、IfValueTF
、IfBooleanTF
,注意用法。 - 结合{minted}的
\newminted
命令,能够方便定制基于{minted}的语法高亮。 - {minted}内部使用了{fancyvrb},要定义新的minted环境,必须包含命令
\VerbatimEnvironment
,以下定义了cpp代码环境(minted.pdf,P30):\newminted{cpp}{gobble=2,linenos} \newenvironment{env} {\VerbatimEnvironment\begin{cppcode}} {\end{cppcode}}
\newtcblisting
、\DeclareTCBListing
等建立的列表不须要如此!
编译过程注意如下几点(以xelatex编译为例):ui
- {minted}将制表符转义为形如
^^T
的符号。在xelatex的编译选项中加入-8bit
可避免此问题。 - 因为要调用Python的Pygments库,xelatex的编译选项中应加入
-shell-escape
。 - 在VScode中,即便文件第一行指定了xelatex编译,可是仍使用recipes中的
latexmk
(这道菜的作法和xelatex这道菜的作法不一样!),所以要专门选择recipes中的xelatex
编译。尽可能配置快捷键,见 VScode 配置为 LaTeX IDE
例 2
% !TEX program = xelatex \documentclass{ctexart} \usepackage[breakable,minted]{tcolorbox} %tcolorbox设置:列表无边框、无边距、可跨页、位于页面中心、90%的正文宽度 \newtcblisting{pylistings}[1][]{ frame empty,size=minimal,breakable,center,width=0.9\linewidth, listing only, minted language=python, minted options={ %自动移除前置空白、制表为4字符、mathhe和||内的不处理 autogobble,tabsize=4,mathescape,escapeinside=||, linenos,numberblanklines=false,numbersep=2pt,#1}} \begin{document} \begin{pylistings}[showspaces] |$\sum_{x}^{2}$| |不处理| def prtmotto(n): # 带一个参数参数 for i in range(0,n): print("lift is short, i use Python!") prtmotto(2) \end{pylistings} \begin{pylistings}[] print("若是没有参数,环境开始后也要带一个空的中括号") \end{pylistings} \end{document}
例2定义的列表环境包含了一个参数,方便调整某些代码的格式。使用中要注意如下2点:spa
- 即便没有参数,环境后也要有对中括号“[]”,不然会报错(tcolorbox.pdf中的有些例子也使如此处理的)。
- 参数以逗号分割,所以不能同时传递2个参数,如[showspace,numbers=none]会出现错误!
例 3
例3使用了\DeclareTCBListing
命令,要先加载{xparse,listings},放于{minted}以前。
为方便使用,定义了一个tcb样式pycode
,就是经常使用选项的集合,使用方法也与选项相同。相同的选项参数,后面的设置会覆盖前面的!因此“minted options”选项移动到新列表的定义中,经过有无“*”判断是否使用新添加的选项。
pylistings
是定义的新列表环境,一个可选参数和一个s参数,就是“*”号。使用了“*”就表示要添加额外的列表控制选项(主要控制空格的显示与否)。不然,就按照基本样式定制列表显示。和前一个例子的使用不一样:若是没有添加新选项,环境后无需加中括号“[]”;不然,将新选项放在中括号中,前面加“*”并放于环境名后。
% !TEX program = xelatex \documentclass{ctexart} \usepackage[breakable,xparse,listings,minted]{tcolorbox} \tcbset{pycode/.style={ frame empty,size=minimal,breakable,center,width=0.9\linewidth, listing only, minted language=python}} \DeclareTCBListing{pylistings}{s o}{pycode, IfBooleanTF={#1} {minted options={ %自动移除前置空白、制表为4字符、mathhe和||内的不处理 autogobble,tabsize=4,mathescape,escapeinside=||, linenos,numberblanklines=false,numbersep=2pt,#2}} {minted options={ %自动移除前置空白、制表为4字符、mathhe和||内的不处理 autogobble,tabsize=4,mathescape,escapeinside=||, linenos,numberblanklines=false,numbersep=2pt}}} \begin{document} \begin{pylistings} |$\sum_{x}^{2}$| #不处理 def prtmotto(n): for i in range(0,n): print("lift is short, i use Python!") \end{pylistings} \begin{pylistings}*[] |$\sum_{x}^{2}$| #注意和上一个比较! def prtmotto(n): \end{pylistings} \begin{pylistings}*[showspaces] # test def prtmotto(n): for i in range(0,n): print("lift is short, i use Python!") \end{pylistings} \end{document}
问题:
- "||"中的字符转义后,先后空一格
- 环境名后无参数,且代码第一行为注释语句时,注释语句会被当成参数而报错。仍旧能编译成功,但多出来一个"#"。可传递一个空参数,即
{pylisting}*[]
。
可参考的处理方案
若是一个文档中包含了集中不一样的程序语言,要高亮显示,能够参考以下方法:
\newcommand{\mynewminted}[3]{% \newminted[#1]{#2}{#3}% \tcbset{myminted/#1/.style={minted language=#2,minted options={#3}}}} \mynewminted{mypylb}{python}{autogobble,mathescape,escapeinside=||, linenos,numberblanklines=false,numbersep=2pt} \newtcblisting{pylistings}[2][]{listing only,myminted/#2,#1} %2 %用tcolorbox, breakable选项可跨页 \newminted[mypyc]{python}{autogobble,mathescape,escapeinside=||} \newenvironment{mypy}[2][] {% \def\mypyenvironment{#1}%save the environments \VerbatimEnvironment% \begin{tcolorbox}[#2]% \begin{\mypyenvironment}}% {% \end{\mypyenvironment}% \end{tcolorbox}% } %% 用法 \begin{pylistings}{mypylb} def fun(): #fanhui return \end{pylistings} \begin{mypy}{mypyc}{} def fun(): #fanhui return \end{mypy}
minipage不能跨页(page break),不用考虑。若是代码的第一行使用了“||”貌似有问题,看前面的例子。
{xparse}包
{xparse}的\NewDocumentCommand
或\NewDocumentEnvironment
的使用中,参数(arguments)分为两类:
- 强制性(mandatory)参数(找不到会报错),分别用字母“m,r,R,v,b”表示,在环境名后以大括号“{}”包围实参。
- 可选(optional)参数,分别用字母“o,d,O,D,s,t,e,E”表示,在环境名后以中括号“[]”包围实参。
- 大写的字母通常要求提供一个默认值,如
{s O{test} m}
。 - 不是必须有强制性参数!强制性是参数设置的属性。能够设置2个可选参数。
- 若是要定义的参数很少,比较方便的是在其余参数前加s参数(BooleanTrue),后跟其余参数。测试中只用一个o参数会报错,但又不想用强制参数,因此前面加s,须要了加个星号后跟参数,不须要的话什么都不作。比较方便。
代码使用Jupyter Notebook样式
- 在Jupyter Notebook或QTconsole中输入代码,并保存为LaTeX文件。
- 从中找到“In :”和“Out:”的颜色。
- LaTeX文件中:定义颜色;代码前加“In :”或“Out:”,并添加颜色。
- 也能够之间在Jupyter Notebook中输入为Markdown,导出为LaTeX,而后调整样式。
- 这是看到:Mckinney201七、VanderPlas2017后想到的。
后记
学生实训,临时起意,给学生讲Python基础。先是用{listings},后来不满意。直接用{minted},又想控制部分代码的空格显示。用了{tcolorbox}后,仍是想很好的控制空格显示,发现用网上的方法和自定义函数并不能令本身满意。看{tcolorbox}文档,接触{xparse}中的参数控制,造成了最后一个例子的结果。
记录上面过程,比较辛苦,但总归是有了两种以上的方法可供选择,这应该是好事!
参考文章
https://tex.stackexchange.com/questions/124657/combine-minted-and-tcolorbox