原文鏈接:LaTeX 的罪與罰 - 樸素的貝葉斯的文章 - 知乎

作為 LaTeX 開發者,看到這種嘲諷自然是非常 angry 的。本來並不想趟這個混水,然而眼見著贊數一天天漲上去,還居然進了精華區,實在忍不住只好註冊了貴乎來說幾句。

你們啊,要……還是要提高自己的知識水平!我也給你們著急啊,真的。

一些問題的解釋

原文章中大多數問題還是在於「姿勢不正確」。不過作者並沒有把完整的代碼放出來,我們這裡只能根據隻言片語嘗試構造出一些問題。當然,我沒有……沒任何……的意思。

fullcite

我們來構造一個代碼示例:

% mytest.tex
documentclass{article}
usepackage{biblatex}
addbibresource{ref.bib}

egin{document}

fullcite{ren2015faster}

fullcite{girshick2015fast}

fullcite{sharif2014cnn}

printbibliography

end{document}

其中的 ref.bib 如下:

Google Scholar 搜索 cnn 的前三項結果

@inproceedings{ren2015faster,
title={Faster r-cnn: Towards real-time object detection with region proposal networks},
author={Ren, Shaoqing and He, Kaiming and Girshick, Ross and Sun, Jian},
booktitle={Advances in neural information processing systems},
pages={91--99},
year={2015}
}

@inproceedings{girshick2015fast,
title={Fast r-cnn},
author={Girshick, Ross},
booktitle={Proceedings of the IEEE international conference on computer vision},
pages={1440--1448},
year={2015}
}

@inproceedings{sharif2014cnn,
title={CNN features off-the-shelf: an astounding baseline for recognition},
author={Sharif Razavian, Ali and Azizpour, Hossein and Sullivan, Josephine and Carlsson, Stefan},
booktitle={Proceedings of the IEEE conference on computer vision and pattern recognition workshops},
pages={806--813},
year={2014}
}

原作者是在 Windows 上面用 WinEdt 自帶的 PDFTeXify 編譯的。手邊沒有 WinEdt,那就模擬一下結果。首先開命令行用 pdflatex mytest 編譯一下:

LaTeX Warning: Citation ren2015faster on page 1 undefined on input line 7.

LaTeX Warning: Citation girshick2015fast on page 1 undefined on input line 9.

LaTeX Warning: Citation sharif2014cnn on page 1 undefined on input line 11.

LaTeX Warning: Empty bibliography on input line 13.

[1{/usr/local/texlive/2019/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
(./mytest.aux)

LaTeX Warning: There were undefined references.

出了一堆 undefined citation 的警告,PDF 裡面引用又全都顯示不出來,so,滿意了吧?不過請把提示信息讀完

Package biblatex Warning: Please (re)run Biber on the file:
(biblatex) mytest
(biblatex) and rerun LaTeX afterwards.

)</usr/local/texlive/2019/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb
></usr/local/texlive/2019/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on mytest.pdf (1 page, 20359 bytes).
Transcript written on mytest.log.

所以,你還需要再跑一下:

biber mytest
pdflatex mytest
pdflatex mytest

現在 PDF 裡面該有的就都應該有了:

含有參考文獻的時候 LaTeX 要編譯多次,這個應當屬於常識。編譯的消息窗口很有用的,要做什麼它明明都說了,不看怪誰呢。

PDFTeXify 那一類自動編譯腳本有的時候沒那麼靠譜,請切到命令行模式手動編譯。不過大概率你可能還是直接點了 WinEdt 的編譯按鈕。在不清楚按鈕背後究竟有什麼東西的時候就直接用,這個嘛,請不要受某些國產軟體「一鍵 xxx」的影響。

PS:我覺得 latexmk 就很靠譜,不知道為什麼 PDFTeXify 不夠 robust?


ibentry

作者表示 fullcite 方案失敗,於是換了 ibentry。其實這時已經陷入了危險的境地:上面那個方案是基於 biblatex/biber 的,現在又換到了 BibTeX,這兩種方案並不能混用。Anyway 先假定知道這一點,再構造一個例子:

documentclass{article}
usepackage{bibentry}
ibliographystyle{plain}

egin{document}

egin{itemize}
item ibentry{ren2015faster}
item ibentry{girshick2015fast}
item ibentry{sharif2014cnn}
end{itemize}

ibliography{ref.bib}

end{document}

然後編譯(圖省事直接用 latexmk -pdf mytest):

嗯,是隻有 itemize 的幾個點。

於是搜文檔,果然是 NULL。找了一圈真沒發現文檔,這個應該確實是個 bug。不妨考慮去買張彩票。下面是手動生成文檔的方法,建議跳過。

<!--

CTAN 頁面中顯示 bibentry 屬於 natbib 的一部分,然而打開 natbibdoc 目錄只有如下這些:

  • README.1st
  • README.v831b
  • natbib.ltx
  • natbib.pdf
  • natnotes.pdf
  • natnotes.tex

文檔裡面搜索也沒有發現 bibentry 相關說明。所以看起來要麼就真的沒有文檔(現在 CTAN 不接收不帶文檔的包),要麼就是作者忘了。打開 source 目錄:

  • bibentry.dtx
  • bibentry.ins
  • natbib.dtx
  • natbib.ins

編譯 bibentry.dtx 可以得到文檔。

-->

其實 Google 搜索一下也可以找到文檔,不過這不重要。一種正確的寫法是用
obibliography
代替 ibliography(並且要放在 ibentry 前面):

另一種是作者提到的「額外寫一句
obibliography*
」:

注意這兩種結果並不一樣,前者是把原來的 thebibliography(即參考文獻表)隱藏起來,然後用 ibentry 給出其中的條目;後者則允許插入原來的 thebibliography。至於為什麼要這麼麻煩,(這個包的原理是重定義 thebibliography 裡面的 ibitem,然後存儲到一些宏裡面。而 thebibliography 存儲在外部文件 <jobname>.bbl,那就只有預先把它讀進來,而且還不能破壞和原來參考文獻機制的兼容性),簡單、現代的方法就在上面(biblatex),但你自己選擇棄療了……


! LaTeX Error: Missing egin{document}

begin document 就在這 LaTeX 你瞎麼 不會報錯能閉嘴麼 能不瞎 bb 麼

這是個相當經典的問題,但卻不太容易搜索到靠譜的解決方案。真的忘記寫 egin{document},或者編譯錯了文件,確實也會報這個 error;但絕大多數時候,明明這行代碼就白紙黑字寫在那兒卻還是「Missing egin{document}」。原因在於,LaTeX 不允許在導言區出現任何排版語句(shipout),只有宏包調用、宏定義、選項設置等才允許出現,所以不小心多輸入了一個字母,就會報錯:

documentclass{article}
A
egin{document}
end{document}

另外,.aux 輔助文件也是在導言區(隱式)載入的,所以如果輔助文件由於不可知的原因(上一次編譯失敗、異常讀寫、高能宇宙射線等)掛了,其中的某些命令在重複編譯時就會被錯誤執行,然後產生排版語句(即使是空的分段也算!),就出現了這個報錯。經驗之談:出現奇怪的問題,先刪乾淨輔助文件再編譯一次

最後,某些不可見字元,如 BOM(U+FEFF,Byte order mark)、LRM(U+200E,Left-to-right mark)等也會造成這個問題,而且不幸的是肉眼還看不出來。解決的辦法是複製問題代碼到靠譜的程序(推薦 Unicode code converter)檢查是否有可疑的字元。多說一句,LaTeX 在 2018 年 4 月之後將 UTF-8 設為了默認編碼,文件開始的 BOM 將不再引發問題。所以建議更新 TeX Live 到最新版。


參考文獻中的 URL

Runaway argument?

BIBentryALTinterwordspacing W.~Commons, ``File hyperspectralcubejpg ETC.! Paragraph ended before BR@c@bibitem was complete.

<to be read again>

parinter word spacing 是說我單詞中間的空格有問題唄,懂英語的人,話還是會說的吧?

顯然原作者並不曾瞭解過怎麼讀報錯信息。只要稍微靜下心來看一遍,就可以看出來:

  • 第一行是 error 的類型,這裡是「runaway argument」,即「參數失控」
  • 第二行給出了 error 發生的上下文,這裡 BIBentryALTinterwordspacing 只是一個命令,其實與 error 本身是無關的,只是不巧出現在了不該出現的地方,因而被誤認為是 error
  • 第三行說明瞭 error 的原因,這裡是說段落在命令 BR@c@bibitem 完成之前段就結束了

TeX 裡面定義宏時,默認不允許喫進去的參數(實參)裡面帶有 par,除非手動添加 long 聲明,這個可以理解為一種簡單的預防措施(在 TeX 發明的上古時期,計算機性能極端受限。一旦出現異常,但由於參數中不允許出現 par,TeX 便會在下一個段落之前停下;否則這個參數可能會一直喫到文件結束,這時候機器可能就掛了)。明知不能分段而偏要分段,BibTeX 自然不會犯這種低級錯誤。所以,問題就是參數本身出現了意外。這裡其實是因為 URL 中的 % 被當作注釋處理,因為之後的 } 就無法匹配,使得參數一直喫到下一處分段而引發這個錯誤。

作為「LaTeX 普通用戶」,你當然可以不需要知道這些。但你會上網吧?請找一個靠譜的搜索引擎,然後把這個錯誤輸進那個搜索框裡面去(上下文就不用帶了,這不是給人看):

點擊第一條結果(沒搜到這個結果?所以上面我要強調靠譜二字),就是 TeX.StackExchange 上的這個問題:

是不是一樣的報錯信息?(忽略上下文)

是不是一樣寫了網址?

是不是網址裡面一樣有個 %

回答只有那麼幾句話,核心就是用 url 或者 hyperref 包,或者手動把 % 替換成 \%,這個真的很困難嗎?

問題並不在於 TeX 給的報錯信息有多麼晦澀難懂和反人類,而是在於,你真的有過稍微仔細地看一眼這幾行報錯信息的努力嗎?

接下來原文作者試圖解決詞間空格的問題,希望你現在能夠知道,這些努力就是徒勞的,因為由於你的斷章取義從一開始就走入了歧途。

我嘗試瞭如下方法:

……都失敗了。網上查詢無果,自己翻看 PDF 文檔,在其中花費了半個多小時努力尋找,眼睛都要瞎了,最終發現 misc 不支持 url 欄位!!! 那為什麼不提示「不支持 url 欄位」?而且憑什麼故意不支持 url 欄位?一個叫做「雜七雜八」的信息模版,就是為了容納雜七雜八的信息的,連一個互聯網來源鏈接都無法支持,何等的丟人現眼。

作者翻看了文檔,這很好,值得表揚。隨後他得出了結論:「misc 不支持 url 欄位」,並且聲淚俱下地把它批判了一番。

然而如果找對了文檔,並且真的看了,那麼,請看 btxdoc.pdf 的第 3.1 節 Entry Types,在第 8 頁從上面數第 2 自然段:

ignored The field is ignored. BibTeX ignores any field that is not required or optional, so you can include any fields you want in a bib file entry…

後面的 misc 中確實沒有把 url 作為 required 或者 optional,那麼就應該被理解為 ignored,換句話說寫不寫都沒有任何影響。事實上,這篇文檔中根本就沒有出現 URL 這個詞,因為那個時候 URL 還就沒有出現……

至於為什麼 URL 還會導致 error,那顯然是由於作者用了其他的參考文獻樣式,不管怎麼樣,使用任何東西之前請閱讀相應的文檔。而且順帶一提,作者之前所使用的 biblatex 裡面,url 是作為 misc 的 optional 欄位。(biblatex 辣麼好用你換掉他作甚?)

要想在 misc 中加 url,要這麼寫:

@misc{crappyLaTeX,howpublished = {url{xsdfsaefaef}}}三重括弧,最為致命。那麼喜歡搞異構的 struct,建議 LaTeX 乾脆把 abs,article,inproceeding 全都搞成不一樣的好了,你們滿意了,我們用戶也乾脆別用了。噢我差點忘了,這個 bibitem 不是我自己手敲的,是從 wiki 上引用下來的,人家 wiki 自動生成的格式,bibtex 處理不了,是 wiki 所有的格式都錯了呢,還是 bibtex 有病呢?

括弧要匹配,難道不是理所當然的嗎?還是覺得三重括弧很多?(建議瞭解 Lisp)以及,無論是 misc 還是 article 還是什麼,它們插入 URL 的方法都是一樣的:

  • 直接 url = xxx,然後交由給定的參考文獻樣式自動添加 url
  • 或者手動寫 howpublished = {url{xxx}}

至於 wiki,

已經寫成這樣了再(裝作)看不懂我們也沒有辦法。


宏包衝突

接下來又遇到了一個問題:

pdfTeX warning (ext4): destination with the same identifier (name{cite.mls2018_ pub}) has been already used, duplicate ignored <to be read again>


elax
l.432 ibitem{mls2018_pub}

實際上這邊是兩個問題,卻被原作者混為了一談。Identifier duplicate 的問題其實只是個 warning,而且是在這裡是完全可以忽略的。後面的確是一個 error 的樣子,但作者沒有給出完整信息,表示無能為力。

作者憑著探索熱情繼續查找,發現根源是 bibentryhyperref 的衝突。同時,它還列出了一大串會衝突的宏包,彷彿食物的相生相剋。

宏包衝突本是個很正常而且不可避免的問題。歸根結底,是因為同樣的命令只能定義一次。後面的定義要麼是覆蓋原來的,要麼就是報錯。有人要問,那 Python、JS 什麼的那麼多庫不也可以和平共處嗎?請問 Python 裡面是怎麼 import 的,import 進來的庫是不是還得加一個前綴?不加前綴你知不知道別人的模塊裡面會不會加進奇怪的東西?

LaTeX 的機制決定了某些介面只有唯一的寫法。section 就必須叫 section,否則所有的文檔就要全部改寫。剛有 LaTeX 的時候,PDF 還不知在哪兒;後來人們看 PDF 是好的,又希望可以支持 fancy 一點的功能,比如超鏈接、書籤這種。So,惟一的辦法就是 redefine section 這些命令。那你怎麼能保證別人不會先改了這個命令,讓你無處可改?一句話,沒有辦法,只有認了。(要不試一試寫 hyp@section 這樣的東西出來?)

這裡列的表可以簡單說明一下,以防不明真相的喫瓜羣眾被嚇到。

  • Hyperref 和 preamble pages 衝突
  • Hyperref 和 Fancy headers 衝突
  • Hyperref and Algorithm 衝突
  • Hyperref and Algorithmic 衝突

hyperref 是衝突大戶,這個也應當屬於常識。除非特殊說明的,比如 cleverefalgorithm 一類,其他時候都應該保證 hyperref 在最後調用

  • Algorithms and Pseudocode 衝突

廢話,兩個包乾的是差不多的活,介面又差不多,沒事為什麼要兩個一起用?同類的還有 biblatex 和其他基於 BibTeX 的包,底層機制都不一樣不衝突那可見鬼了。

  • PGF 和 double subscripts 衝突

沒事請不要把十二年前就修好的 bug 拉出來……

  • XeLaTeX 和 pdftex driver 衝突
  • XltXtra and Graphicx 衝突
  • Amssymb with Xunicode 衝突

很多包是為 8-bit 的引擎寫的,後來有了 XeTeX、LuaTeX 這些東西就通通可以規避掉了。以及,沒有必要畫蛇添足,graphicx 包加上 [xetex] 這樣的選項純粹是多餘的。只要涉及 ASCII 之外的東西,請一律使用 XeTeX 或者 LuaTeX 編譯。[1]

  • Caption 和 Subfig 衝突

subfig 包已經調用過了 caption,再調一遍還用不同的選項那只有報錯了。很多現代的宏包都提供了 xxxsetup{<key>=<value>} 的寫法,這樣可以很好地規避宏包選項的衝突。

PS:這段話中英文夾雜得怎麼看怎麼彆扭。國內的博客大多是東抄西抄,這個宏包衝突的介紹不知道轉了幾遍:

  • blog.sina.com.cn/s/blog
  • latexstudio.net/archive
  • macfreek.nl/memory/LaTe

求求你們花幾分鐘找一下原始資料吧!


中文字體支持

Pull 下來一編譯,您猜怎麼著!噢我的老天爺,放到 mac 上編譯不好使了哈哈哈!一個跨平臺的軟體,入了鄉還不能隨俗的呀。

TeX fontset `mac is unavailable 是什麼鬼?老子行走江湖從未見過這種錯誤。查來查去,很多人都說改一改字體,用 mac 支持的字體就好了,我前前後後改了數十個字體,挨個去 macOS 的 Font 管理器裏對照,都有啊,有這個字體啊。

字體,尤其是中文字體的跨平臺方案,在過去一直是個老大難問題。然而朋友,現在 2019 年都已經過去一半了,你的知識還在上一個十年,我們能有什麼辦法呢?

所有包含漢字的文檔,請一律使用 XeLaTeX 編譯,配合 ctex 文檔類/宏包,可以保證不出問題。非要用 pdfLaTeX,就怪不得別人了。(不知道 XeLaTeX?那你可能學了假的 LaTeX)

後來我乾脆從我自己的 Windows10 上下載了所有的字體

我把 windows 10 裏的整個字體文件夾壓縮好了,安裝在mac上。

老子現在有五百多個字體,能繞地球一圈,連微軟雅黑我都有,重構字體緩存吧!字體放到 texmf 什麼鬼的文件夾去吧!重構 LaTeX 字體緩存吧!編譯吧 latex 君!

還是這個錯誤。

ctex 默認配置在 macOS 上不需要微軟雅黑,字體緩存也不需要重建(macOS 上的 XeTeX 不用 fontconfig 庫),更不需要「放到 texmf 什麼鬼的文件夾去」。提供教程的傢伙需要向全國人民謝罪。

經過三天的調試,我改用了 XeLaTeX,刪除了所有字體的自定義,全都 tm 默認吧,然後居然能編譯了???

使用默認配置進行測試應該是第一分鐘就做的事情,感覺這三天是白白耽擱了。表示同情。

我這正文都是宋體,該強調也強調了,怎麼?哎!

這是為什麼啊,怎麼宋體裡面多了楷體???我原文怎麼寫的?這就是一個強調啊?怎麼不給斜體,不給粗體,給了個奇奇怪怪的楷體

中文從來沒有斜體,使用楷體來對應西文中義大利體的做法,是一種常規操作。不給斜體和(偽)粗體,是對你的排版質量負起最低限度的責任。[2]

字體字型大小還和正文不匹配

請區分「字型大小」與「字面」。(這確實是一個問題,然而我敢打賭這個詞你都沒聽過)

也沒像英文一樣給我多加半個空格隔開

中文從來不需要使用空格分詞,何況,寫英文你會手動加上空格的吧?


抄錄環境

作者為了顯示 emph{},先後嘗試瞭如下方案:

  • emph{}
  • \emph{}
  • $\ ext{emph}{}$
  • $ackslash$...

最後一條還是「六年 LaTeX 專家」出手的結果,然而還是沒有搞出來,這「專家」真的不夠給力誒。

記住了!這個叫抄錄環境(verbatim),行內的直接寫 verb<char>...<char>,這邊 <char> 隨意但前後要一致,裡面隨便怎麼寫。所以,你要的東西就是 verb+emph{}+

\ 是換行,表格裡面的那種換行。既不是分段,也不是什麼轉義(TeX 裡面只是額外定義了一些命令來表示這些特殊符號,和其他語言裡面加反斜槓轉義是有本質不同的)。而第三種、第四種寫法屬於蓄意濫用數學環境,請不要這麼做。

下面列了幾個「可以滿足要求」的方法,你選擇哪個?(verb 會默認使用等寬字體,其餘默認正文字體)

PS:原文圖裡面 TeX 後面漏了 {} 或者 <space>,而且引號寫反了……

輔助文件

讓我們來找個答辯模板編譯一個PPT吧,就從上一屆畢業生那裡拿一個好使的來好了。

曾經親眼目睹編譯成功的我,這次又栽在了起跑線上:

編譯之前刪掉原來的輔助文件,這是常識。把別人的東西拿過來直接跑基本不可能成功,這也是常識(誤)。

沒有問題創造問題也要上,不然怎麼點亮 github 的貢獻方格呢。

我們刷綠方塊都是靠改 typo 的(大誤)。

「握日,怎麼生出這麼多不認識的文件???比 Visual Studio 還多!文件夾都快填滿了!」

……通情達理的我知道每個文件背後,都有一個辛勤的開發者,花費無數個日日夜夜為這個格式的臨時文件設計語法、宏、變數、函數、數據格式……。每一個臨時文件都像一個祕密的寶藏等待著我去挖掘。我想到只要把這些中間文件都弄懂,我就是半個專家了。我已經迫不及待了,快讓我看看有多少種中間文件需要學習呀!彼之寶藏,我之垃圾。

輔助文件無非這麼幾類:

  • 第一遍生成之後,第二遍再讀進去,以生成交叉引用、參考文獻、目錄、索引等(可能需要外部程序參與),比如 *.aux*.bbl*.toc*.idx*.ind
  • 日誌,如 *.log*.blg
  • 目標文件的中間產物,如 *.dvi*.xdv
  • SyncTeX 相關,用於 PDF 與源文件之間的跳轉,如 *.synctex*.synctex.gz

宏包那麼多,為了避免衝突,當然是生成不同的文件最簡單了。.gitignore 裡面寫的,一大半保證你不會遇到。反過來,遇到的 edge case 也未必能完全覆蓋,所以用之前最好自己 check 一下。

關於中間文件的語法,如果是被 TeX 讀進去的,那自然還是 TeX 的語法,並不會很詭異;日誌都是純文本,識字就能看懂。反正編譯中間沒必要管,編譯完了放心大膽地刪。編輯器一般都會有配套的工具,自己寫個腳本也應該沒什麼困難。


一些感悟

這是我使用 LaTeX 的第三年,踩了很多坑後,我也開始有了對 LaTeX 的一些感悟。

不巧,這也是我使用 LaTeX 的第三年(從我 2015 年年底裝 CTeX 套裝開始算,四年不到),所以我也有「對 LaTeX 的一些感悟」。

入門之前

在擁擠的辦公桌前,面對 doc 文件夾下三千多個 PDF readme,我知道我這輩子都沒辦法做一個 LaTeX 科班生。然而,命運不會等人,我手中小小的報告,常常 24h 內就必須要飛到老師的郵箱中。

比較不幸的是,大多數人用 LaTeX 都是被迫 / 半被迫的:你的老闆可能並不會管你會不會用就直接把你逼上梁山,建模比賽別人都用我不用就沒獎了(誤)。但沒有什麼辦法,24h 內掌握 LaTeX 就是不現實,至少得勻出幾個禮拜到幾個月的時間才能上手。既然知道「老闆可能要我用一個之前沒碰過的工具」,是不是應該提前預留一些學習時間呢?

我也希望自己能做一個弄明白 LaTeX 的人。然而可惜的是,我或許永遠無法將 LaTeX 看作一個「專業工具」,拿出鑽研編譯原理的勁兒來啃透 LaTeX。

這或許是因為,在座的你我需要的無非是排個章節、插個圖、上下標、來幾行公式……我們需要一個能好好地把字母排列到理想位置的「效率軟體」,而不是一個慢吞吞又挑三揀四難以融洽的「活祖宗」。

這是很多人的困擾:我就是隻要寫個文章為什麼要把 LaTeX 搞得這麼清楚?此時可以類比如下問題:

  • 我只是寫個 C 的 Hello world,怎麼還要學命令行、學 Linux、學 Makefile、學 Git……?
  • 我只是學計算機、學數學、學 xxx,為什麼要會英語?
  • 我一個理科生為什麼要學語文?我一個文科生為什麼要學數學?買菜又不用三角函數微積分解析幾何……

具體問題具體來說。不管你認不認可,(La)TeX 就是一個完備的編程語言,雖然你需要的可能只是「作為標記語言」的那一個子集。所以,準備上手之前,請務必認清楚自己的身份

  1. 我要按照模版寫畢業論文、建模論文、期刊論文

你需要找一些合適的入門材料,學習基本的語法。有模版請嚴格按照模版的說明操作,不要根據自己的喜好做任何修改(你的感覺與偏好在這個階段極有可能是有問題的)。重點請放在文章的內容,而不是文章的格式。出現任何問題請找模版作者,沒有必要試圖自己解決。

2. 我要記筆記、出試卷、寫書

同上,請先從入門開始。熟悉基本流程之後再放飛自我,劉海洋的《LaTeX 入門》可以備在手邊隨時翻閱。每天讀兩次《入門》,每次都有新收穫。

3. 我要系統學習排版知識,寫模版、寫宏包

你可能確實要拿出「鑽研編譯原理的勁兒」。排版的水可能比你想像的還深,而 TeX 跟主流編程語言大相徑庭也需要一些時間來掌握。Google、GitHub 和 StackExchange 將會是你的好朋友,以及,英語是必須的。

4. 我要寫世界上最好的排版引擎幹掉 TeX

請聯繫 @李阿玲(逃

5. 老闆讓我幹什麼我就幹什麼

祝好運,不送。

入門教程

知乎上老生常談的問題,前輩們的回答可以認真讀:

  • 如何在 1 小時內快速入手 LaTeX? - 劉海洋的回答
  • 如何從零開始,入門 LaTeX? - 孟晨的回答
  • 自學 LaTeX 可以讀什麼書入門? - 劉海洋的回答、孟晨的回答

當然也可以選擇看下面的:

剛入門的頭幾步將會在很大程度上決定之後的路好不好走。不論是看了譚浩強的 C 語言,還是不知道從哪裡找來的 LaTeX 教程,後果都是出現一堆稀奇古怪的問題,自己還找不到解決方法。所以,我們非常希望新手能夠選擇一些靠譜、合適的入門教材。

現在(2019 年 7 月),我們只推薦下面這些材料:

  • 一份(不太)簡短的 LaTeXe 介紹(lshort) [PDF] [GitHub]
  • 一份簡短的安裝 LaTeX 的介紹 [GitHub]
  • @劉海洋 的《LaTeX 入門》(跳過 CTeX 套裝的部分)

lshort 強烈建議完整讀一遍,普通文章排版所需要的幾乎全部功能這裡都包含了。找不到直接去《LaTeX 入門》的相關章節翻閱(當字典查)。其他網上的資料,wikibook 上的教程可以參考,知乎請認準那幾位的回答,b 站魚龍混雜謹慎使用,而 csdn、科學網博客、x 度文庫請絕對不要看

有人帶自然很好,但請先判斷他的水平。最簡單的依據:如果他還在用 CTeX 套裝,或 WinEdt 7.0 及以下,或代碼裡面出現了 CJK 環境,那麼請立刻遠離(當然,僅限 LaTeX 方面)。

發行版建議使用最新版 TeX Live(目前是 2019),或者在線使用 Overleaf(最好自備梯子)。CTeX 套裝絕對不要用

最後一點提醒:如果你不小心學了假的 LaTeX,建議回頭重讀一遍以上列出的入門材料。

如何找模版

為了寫出符合學校要求的論文,誰都需要一個好用的模版,而不出意外地,我也是其中的一員。

  • 實驗室的演算法大神世豪搞了個模板用,折騰折騰,一編譯,好使!
  • 我拿來用,不好使,浪費了一兩天時間。
  • 實驗室編碼大神益達用了個模板,折騰折騰,編譯一下,好使!
  • 我換成他的,不好使,浪費了一兩天時間。
  • 我上 Github 下載了一個的 ZJUthesis
  • 不好使,浪費了兩三天吧。
  • 換成另一個 github 上的 zju 模板,不好使。
  • 這時候數學優化大神蘿蔔給我了一個師兄自用的模板。
  • 我試了一下午,不好使。

懷疑你在黑 zju 然而我找不到證據……

首先,學長 / 學姐 / 大神 / 巨佬拷給你的模版幾乎一定是不好用的。目前大多數高校的模版都掛在了 GitHub 上面,有些還發布在了 Overleaf 或者 CTAN 上面,請認準這些(半)官方渠道。(請問你會選擇 pip、Anaconda,還是濕兄拷給你的 TensorFlow ?)

其次,GitHub 上面找模版,居然還去試了幾個。沒有經驗可以告訴你一點經驗:

  • 沒有 README、LICENSE、.gitignore 的可以直接忽略(原文章居然吐槽了 LICENSE 這我還能說什麼?)
  • Commit 很少,幾個月內又沒有什麼更新,建議不要用
  • Issue 越多說明積累的問題越多,也就意味著用戶越多,當然前提是作者要去處理 issue
  • Star、fork、watch 都很少的話請小心使用,不過也有可能是比較新的緣故
  • 使用 dtx 作為源代碼、有測試文件、用 ci 的模版往往更靠譜一些

最後,下載下來覺得不好使。請問有看過模版的使用說明嗎?有完全按照模版提供的編譯說明來跑嗎?這樣再出現問題應該直接聯繫模版作者 or 跑去 GitHub 提 issue。一個靠譜的模版作者應當可以解決你的問題。

Debug 策略與提問的姿勢

生活總是充滿苦澀,我選擇了一個 error 最少的 cls 文件,從 0 開始,一點一點把各個模板好使的語句慢慢粘貼過來,形成一個巨大的 tex 文件。

原文作者顯然完全沒有 debug 的能力。首先要做的是分解問題,而不是把所有東西全部堆過來來碰運氣,這樣只能變成一座 shit mountain。

我們這裡可以通過一個例子說明:ctex-kit #331

原來的問題簡單得很:

documentclass{ctexart}
usepackage{fancyvrb}
egin{document}
egin{Verbatim}
鳶尾花
end{Verbatim}
end{document}

可以看到左邊的引號後面多出了一個空格:

然而,該用戶因為知道「zhspacing 包是用來解決中英文之間的空格,包括代碼塊中中英文之間的空格」,所以想用 zhspacing 包來處理,結果卻遇到了 Linux 下沒有 SimSun 字體而產生的錯誤,這才過來報告 issue。

該用戶發現在 Windows 上配合 zhspacing 包可以實現想要的效果:

觀察仔細可以發現這裡的引號其實是蝌蚪引號 U+2018 Right single quotation mark,而不是編程語言中一般用的 U+0027 Apostrophe。所以這其實並不是正確的解決方案。

暫且不討論引號的問題。所謂的「窮折騰」從一開始就完全帶偏了節奏,也在一定程度上招致了開發者的不滿。我們可以看到,該用戶自始至終就沒有提供一份足以展示問題的代碼,而只有代碼本身才是解決問題的鑰匙。

接下來,@yihui 提供了代碼(第一份代碼只是引號的正常寬度,與本問題無關),那麼問題就好解決多了:

documentclass[UTF8]{ctexart}
usepackage{color}
usepackage{fancyvrb}

ewcommand
{VerbBar}{|}

ewcommand
{VERB}{Verb[commandchars=\{}]}
DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\{}}
usepackage{framed}
definecolor{shadecolor}{RGB}{248,248,248}

ewenvironment
{Shaded}{egin{snugshade}}{end{snugshade}}

ewcommand
{StringTok}[1]{ extcolor[rgb]{0.31,0.60,0.02}{#1}}

egin{document}

egin{Shaded}
egin{Highlighting}[]
StringTok{"鳶尾花"}
end{Highlighting}
end{Shaded}

end{document}

這個代碼已經足夠簡短,並且也展示了問題。當然還可以繼續簡化:

  • 顏色有關的代碼可以通通刪去
  • 定義的 VerbBar 等命令沒用到,刪掉
  • Highlightingfancyvrb 宏包自帶的 Verbatim 代替

這樣我們就得到了一開始的那份問題代碼,於是終於可以開始 debug 了。

  1. 使用 LaTeX 的標準 verbatim 環境(注意大小寫),發現是正常的。

2. 使用 article + xeCJK 代替 ctexart 文檔類,同樣出現問題。

3. 在 xeCJK 的文檔中搜索有關抄錄環境的問題,可以找到 Verb 選項和 xeCJKVerbAddon 等命令。根據說明,我們可以把它添加到 fancyvrb 宏包的 formatcom 選項中:

documentclass{article}
usepackage{xeCJK,fancyvrb}
DefineVerbatimEnvironment{Highlighting}{Verbatim}{%
commandchars=\{}, formatcom=xeCJKVerbAddon}
egin{document}
egin{verbatim}
鳶尾花
end{verbatim}
egin{Verbatim}
鳶尾花
end{Verbatim}
egin{Highlighting}
鳶尾花
end{Highlighting}
end{document}

這時修補過的 Highlighting 就可以表現正常了(Verbatim 用來對照):

4. 查看代碼可以看出,xeCJK 僅為 verbatim@font 打了補丁,而這個是 verb 或者 verbatim 環境內部所使用的字體樣式。如果是其他抄錄環境則需額外定義(listings 宏包由於使用自己的一套機制 xeCJK 對此單獨做了修補)。

到此問題便得到了解決。我們可以總結一下:

  • 有問題請儘快整理出示例,向更有經驗的人求助。一知半解 + 窮折騰很有可能會把問題代入死衚衕。
  • 一定要給出最小工作示例(MWE)
    • 應當是一個完整的、在你的電腦上能編譯的 LaTeX 文檔
    • 何為完整?以 documentclass 開始,以 end{document} 結束
    • 在你電腦上的編譯結果,應當能復現問題,或體現需求
    • 與復現問題和體現需求無關的代碼應儘可能少,如各種宏包的載入、自定義的命令等
    • 嘗試更換為標準文檔類(articlectexart)等
    • 如果復現問題需要其他文件(圖片、bib 等),請把它們和 LaTeX 文檔一起打包
  • 給出 MWE 的過程就是 debug 的過程。這時需要進一步刪掉無關代碼,呈現問題原貌,此時可以:
    • Print 大法好!TeX 的 show 命令可以展示宏的內容,而 LaTeX3 還提供了更多的類似函數
    • 一點點注釋掉無關內容,二分法定位
    • 插斷點,實際上 show 的時候編譯會中止,我們常利用多個 show 來定位 bug

TeX 要面向現代化、面向世界、面向未來

眾所周知,(La)TeX 是一個很古老的東西,很多問題歸根結底都源自於歷史的侷限。「新一代」的引擎 XeTeX 和 LuaTeX 十多年前就進了 TeX Live,阿玲姐姐的那一個也指日可待。然而卻還總有人試圖靠 8-bit 引擎來解決 CJK 問題,對這樣固步自封的行為我們表示遺憾。

語言方面,宏語言捉襟見肘的表達能力確實是一個問題。但 LaTeX3 也在逐漸成熟,二十多年積累下來的方方面面的經驗使得它正在成為標準庫一樣的東西。當有了統一的框架,可以想見開發與使用都將變得更加容易。與此同時,ConTeXt 那邊也在持續地嘗試新的想法,對 variable fonts 和 color fonts 的支持 2017 年就已經做了。所以,在追趕潮流的能力上 TeX 絲毫不比那幾家商業公司差多少(誤)。

作為開發者,我們自然希望用戶的使用門檻可以一降再降,遇到的坑也能夠越來越少。不過,這都建立在用戶自己有嘗試、探索、討論與交流的熱情之上。遇到問題,只會無頭蒼蠅一樣四處亂撞,或者陰陽怪氣地嘲諷,我們只能提醒你:恐怕使用 Word 的能力你也沒有

ye

參考

  1. ^傳統上 TeX 的流程是先生成 dvi,再接後續操作(即「驅動」,如 dvips、dvipdf、dvipdfm、dvipdfmx 等)。插圖、彩色支持是在第二步做的,TeX 並不知道具體細節,所以需要手動給 graphicx 加上選項以指定驅動使其能夠寫入特定代碼(special 命令)。但現在主流都是 pdfTeX、XeTeX、LuaTeX 等「一步到位」的東西,宏包可以自動判斷,不需要也不建議手動指定。
  2. ^楷書、斜體、連筆,義大利體的漢字匹配方案探索 https://mp.weixin.qq.com/s/gd2rB0hjZhPGavGcZKtSOg

推薦閱讀:

相關文章