LaTeX中Python代碼的語法高亮


LaTeX中Python代碼的語法高亮

本文中,“{}”中的字母為LaTeX或Python的包名,只有“Pygments”是Python的包,其他都是LaTeX的包。

LaTeX提供了功能豐富的包(package),以實現某些特定的排版功能。其中,{listings}包和{minted}包主要用於文檔中程序代碼語法的高亮顯示,支持常見的編程語言。

  • {listings}基於內置或用戶提供的關鍵字高亮程序代碼語法,高亮的內容受限於關鍵詞的數量,代碼的着色功能也是有限。
  • {minted}使用Pymgent高亮程序代碼,提供了更多的高亮內容,基本類似在Jupyter Notebook或Jupyter Qtconsole中的代碼高亮。

使用{listings}包

{listings}的使用簡潔明了:

  • 在導言區加載包,並設置包選項。
  • 在文檔區使用\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}包。

{mdframed}和{tcolorbox}都是定制框(box)的包,前者要自己hacker,后者的已有功能十分豐富,且定制功能強大。{tcolorbox}提供了minted庫,通過如下形式之一使用:

  • \usepackage[minted]{tcolorbox}。自動加載{minted}包
  • 通過\tcbuselibrary加載
    \usepackage{tcolorbox}   
    \tcbuselibrary{minted}  %加載{minted}包
    

如果要定義新環境或命令,{tcolorbox}提供了如下命令:

  • \tcbset設置所有tcolorbox的參數。
  • tcolorboxtcblisting環境建立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中的宏):IfNoValueTFIfValueTFIfBooleanTF,注意用法。
  • 結合{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編譯為例):

  • {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點:

  • 即使沒有參數,環境后也要有對中括號“[]”,否則會報錯(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,然后調整樣式。
  • 這是看到:Mckinney2017、VanderPlas2017后想到的。

后記

學生實訓,臨時起意,給學生講Python基礎。先是用{listings},后來不滿意。直接用{minted},又想控制部分代碼的空格顯示。用了{tcolorbox}后,還是想很好的控制空格顯示,發現用網上的方法和自定義函數並不能令自己滿意。看{tcolorbox}文檔,接觸{xparse}中的參數控制,形成了最后一個例子的結果。

記錄上面過程,比較辛苦,但總歸是有了兩種以上的方法可供選擇,這應該是好事!

參考文章

https://tex.stackexchange.com/questions/124657/combine-minted-and-tcolorbox


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM