> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-tw/shen-ru-wen-zhang/14-how-do-tex-engines-typeset-tables.md).

# TeX 引擎如何排版表格

## TeX 引擎如何排版表格

## 前言：本系列涵蓋什麼？

製作美觀的表格可能是一項耗時的工作——無論你使用的是視覺版面工具、LaTeX，還是像 HTML 或 Markdown 這類標記語言。尤其對 LaTeX 使用者而言，表格排版在許多人的「痛點」清單中名列前茅，或許「tables」是最 [tex.stackexchange 上標籤數量很高的主題](https://tex.stackexchange.com/tags).

除了 tex.stackexchange 上的回答與範例之外，即使只是粗略瀏覽一下關於用 LaTeX 排版表格可取得的支援，也會發現不少與表格相關的資訊資源：

* Overleaf 的 [說明頁面](https://www.overleaf.com/learn/latex/tables) 以及其他網站，例如 [learnlatex.org](https://www.learnlatex.org/en/lesson-08)
* CTAN（Comprehensive TeX Network，綜合 TeX 網路）列出了超過 [70 個 TeX/LaTeX 套件](https://ctan.org/topic/table) 與建立表格相關的
* 整整一本 [使用 LaTeX 進行表格排版的書](https://www.amazon.co.uk/Typesetting-Tables-LaTeX-Herbert-Voss/dp/1906860254)
* 一個極佳的 [線上 LaTeX 表格產生器](https://www.tablesgenerator.com/latex_tables)

只要簡單搜尋 [LaTeX 表格](https://www.google.com/search?q=latex+tables) 就會得到大量結果，列出許多提供協助、建議、範例與說明的網站。

### TeX，而不是 LaTeX

既然關於使用 LaTeX 進行表格排版的文獻如此豐富，還有什麼可寫的嗎——更多表格範例，以及套件指令的列舉／示範？是否有一種切入表格排版主題的方法，能夠引出或聚焦於表格排版的基本原理與概念？有，但這需要一層層剝開 LaTeX 這顆洋蔥……

我們決定推出一系列文章，旨在為讀者提供背景資訊與對底層的說明 *機制* 以 TeX 為基礎的表格排版。與其聚焦於使用特定的 LaTeX 巨集／套件來排版表格，我們將探討其 *底層行為* TeX 引擎：探索構成 LaTeX 巨集命令之基礎的低階排版機制。最終目標是整理並說明以 TeX 為基礎的表格排版核心方法與演算法——希望能幫助讀者／使用者更理解表格為何會有那樣的表現。採用這種方法的一個不可避免的後果，就是剝去 LaTeX 巨集所提供的保護層，接觸那些雜亂的低階細節；一般情況下，使用者都會（而且樂於）被多層 LaTeX 巨集程式碼包裹起來。

研究、撰寫並為這些文章繪製插圖耗費了大量時間，因此我們希望它們 *不* 順帶談及 *美學* 這方面的問題——表格設計是一個充滿主觀偏好的主題，其爭論必須在別處展開……

### 探索 TeX 表格的機制：要如何做到？

為了探索並撰寫 TeX 引擎內部發生的低階機制與流程，例如表格排版，Overleaf 使用 Martin Ruckert 的 [Web2W 程序](https://w3-o.cs.hm.edu/users/ruckert/public_html/web2w/index.html).

傳統上，建置 TeX 會涉及一個稱為 Web2C 的程序，它在 TeX Live 中使用，透過將 TeX 原本的 Pascal 原始碼轉換為相應的 C 程式碼來產生 C 程式碼。該程序產生的 C 程式碼從未打算讓人類閱讀，只供 C 編譯器使用。這種機械產生的 C 程式碼 *極其* 難以閱讀或為了實驗目的進行修改。

相較之下，Web2W 會產生 C 原始碼（可於 [這裡](https://w3-o.cs.hm.edu/users/ruckert/public_html/web2w/ctex.c)）其 *數量級* 更容易閱讀，遠勝於 Web2C 產生的程式碼。因此，Web2W 的 C 原始碼更適合為了學習／實驗目的進行修改。

Web2W 產生的 TeX 版本（「CTeX」）是 *極其* 與 Knuth 的原始程式相當接近：「CTeX」不包含 Web2C 程序所引入的許多變更與增強——例如 SyncTeX、命令列處理，以及透過 Kpathsea 進行檔案搜尋。雖然你會犧牲那些有價值的增強功能，但生成的（Web2W）C 程式碼仍可透過 Knuth 公開的 TeX 原始碼相對容易地瀏覽，儘管 TeX 是以 Pascal 撰寫的。

* **關於名稱的說明：** 嚴格來說，「TeX」這個名稱只能指 Donald Knuth 所撰寫並發表的原始軟體。對其軟體所做的任何修改，都必須為產生的以 TeX 為基礎的排版軟體使用不同的名稱。這裡我們使用 Web2W 程序建構了一個引擎，而它本質上仍是 Knuth 的原始軟體。不過，為免疑義，我們將使用「CTeX」一詞來指以 Web2W 建立的特定版本；同時我們也會用「TeX」來指 Knuth 的原始引擎，或指以 Knuth 的 TeX 原理為基礎的排版語言這個通用術語。我們希望讀者能包涵在嚴格使用正確術語時偶爾出現的疏漏：我們也希望意思／意圖能由上下文傳達。

CTeX 的除錯版本是使用 [Eclipse IDE](https://www.eclipse.org/downloads/packages/)執行的，這使得我們能即時觀察實作低階原始（內建）TeX 指令與演算法的 C 程式碼，這些都是 Knuth 為支援表格排版而設計的。

以下這段短片（約 90 秒）展示了 CTeX 引擎在 [Eclipse IDE](https://www.eclipse.org/downloads/packages/):

{% embed url="<https://videos.ctfassets.net/nrgyaltdicpt/7drdFwYR6h5xD88XnurDIH/36511f504755ab274f4da2e3f3fc1ce5/TeXtables.mp4>" %}

除了 CTeX，我們也編譯了 e-TeX，以使用幾個 Knuth 原始軟體中沒有的額外原始指令。雖然 CTeX 和 e-TeX 到現在都已是較舊的 TeX 基礎引擎，但它們仍然適合作為探索表格排版機制的基礎，因為那些底層原理仍適用於所有以 TeX 為基礎的排版引擎。

### 為什麼要使用較舊的 TeX 引擎來探索表格？

首先，印刷版書籍 [TeX:The Program](https://www.amazon.co.uk/Computers-Typesetting-TeX-Program-TEX/dp/0201134373)，其中列出並解釋了 TeX 的原始碼，即使它已在 30 多年前（1986）出版，仍然是探索 TeX 內部運作的非常便利指南。當然，你也可以自行排版 TeX 原始碼文件，例如參見 Overleaf 專案 [為 TeX、e-TeX 或 pdfTeX 的原始碼文件進行排版](https://www.overleaf.com/latex/examples/typeset-the-source-code-documentation-for-tex-e-tex-or-pdftex/qkgfgyspnhcv)。自 1986 年 TeX:The Program 發表以來，新的 TeX 引擎不斷演進，包括 pdfTeX、XeTeX 和 LuaTeX，這些引擎都引入了 TeX:The Program 中未記載的功能與指令，原因很簡單：它們在 Knuth 的原始軟體中並不存在。

對許多核心流程而言，例如 TeX 的表格排版，TeX:The Program 中所記載的程式碼仍然是值得研究的基礎——即使 TeX 的原始碼是以 Pascal 撰寫的。此外，Knuth 的 TeX 相對容易且快速地編譯，特別是透過極其有用的 [Web2W](https://w3-o.cs.hm.edu/users/ruckert/public_html/web2w/index.html) Martin Ruckert 所開發的程序。編譯的容易性／速度使得以簡單方式修改 TeX 方便得多——例如本系列文章稍後會使用的 SVG 圖形建立。

### 了解 TeX 與 LaTeX 的差異

許多讀者已經知道，LaTeX 其實並不是一個 *可執行的* 排版程式，而是一大組指令（*巨集*），而這些指令最終是以一種稱為 TeX 的低階排版／程式語言撰寫的。你的 LaTeX 程式碼只有在被一個稱為 *TeX 引擎*的可執行程式處理後才會產生排版輸出——該軟體位於你的 LaTeX 程式碼（文件）與排版後的 PDF 之間。如今，使用者可以選擇多種 TeX 引擎來排版其 LaTeX 程式碼，包括 pdfTeX、XeTeX 以及各種 LuaTeX 變體。

對 TeX/LaTeX 生態系統較為陌生的人，常常也難怪會被他們遇到的工具所使用的大量晦澀名稱弄得一頭霧水：TeX、LaTeX、pdfTeX、pdfLaTeX、XeTeX、XeLaTeX、LuaTeX 和 LuaLaTeX。若你也有同樣感受，Overleaf 的文章可提供幫助： [名稱裡有什麼：TeX 的多種風味指南](/latex/zh-tw/shen-ru-wen-zhang/55-what-s-in-a-name-a-guide-to-the-many-flavours-of-tex.md) 其中解釋了那些術語的來源與含義。

#### 方言與 TeX 原始指令

每個 TeX 引擎都有一組稱為 *原始命令* 的內建指令，這些指令合起來構成該引擎的 TeX 排版語言「方言」，反映了每個引擎內建的能力。這裡，用來描述 TeX 引擎內建指令的「primitive」一詞並不 *不* 表示那些指令很基礎或簡單，而是表示它們是根本且不可分割的：不是由其他指令構成的（不同於巨集）。所有 TeX 引擎都共享一大組核心原始指令，但有些引擎也包含該引擎特有的原始指令——這便產生了 TeX「方言」的概念。

無論你使用哪一種 TeX 引擎來排版 LaTeX 文件，它的工作就是處理（「執行」）用來撰寫與構成文件的那組 LaTeX 指令（即巨集）。實際上，TeX 引擎會把你的 LaTeX 程式碼（巨集） *重新轉回* 其所包含的 TeX 引擎原始指令，而引擎可以執行這些指令來進行實際排版。你不 *必須* 一定要使用 LaTeX 指令來透過 TeX 引擎排版文件——你 *可以* 選擇完全以 TeX 原始指令來建構你的文件，也就是直接用低階的 *TeX 程式語言* 來完成，這種語言內建於 TeX 引擎中。然而，以今日標準來看，TeX 語言相當晦澀，通常被認為是一門難以程式設計的語言——要達成你的排版目標也可能需要大量內建原始指令，因而使程式設計工作容易出錯且可能重複。

為了避免必須直接以 TeX 語言撰寫，或一再重複輸入同一系列指令，TeX 引擎讓你可以建立稱為「快捷方式」的 *巨集*。透過建立巨集，你可以定義自己的指令，將可能很長且複雜的 TeX 語言原始指令序列（或其他巨集）包裝成單一個「更高階」的指令。TeX 程式設計師可以編寫非常精密的巨集，將大量功能封裝在單一指令中——例如 LaTeX 提供的那些指令。透過使用巨集套件，例如 LaTeX（或 [ConTeXt](https://wiki.contextgarden.net/Main_Page)），文件作者（大多）可免於許多繁瑣細節，使他們能專注於撰寫與排版，而不必一直與 TeX 語言的複雜性與細微差異纏鬥。

## 一開始……

除了設計數學排版與複雜斷行的演算法之外，Knuth 還面臨一項挑戰：讓他的 TeX 軟體能夠排版表格。顯然，任何表格建構演算法都不能過於受限，因為那會讓需要自由建立近乎無限種表格版面的使用者感到受挫。此外，表格儲存格可以包含各種內容，包括數學、圖形，以及被拆成漂亮排版行的文字片段——事實上，任何 TeX 能夠排版的東西都可以。要提供這種彈性，就要求 TeX 的表格建構演算法與 TeX 排版機制的其他部分密切協作。

然而，TeX 引擎為其表格建構能力所提供的彈性付出的代價是：內建（原始）表格排版指令在低階行為上存在許多細微差別與 нюances，而這類指令共有 9 個：

* **`\halign`**, **`\valign`**：核心表格建構指令
* **`\tabskip`**：放置於 \halign 欄或 \valign 列之間的黏結空白
* **`\cr`**：所有表格列的必須終止符「carriage return」
* **`\noalign`**：在 \halign 列或 \valign 欄之間插入內容
* **`\everycr`**：在偵測到 \cr 後要讀取的指令（記號暫存器）
* **`\span`**：雙重功能指令：\span 可建立跨欄或跨列的儲存格，或展開表格前導區中的指令（我們將詳細討論）
* **`\omit`**：略過特定儲存格的樣板
* **`\crcr`**：用於巨集中，以避免使用者忘記必要的 \cr 時出錯

我們在探索表格建構的過程中會遇到這些指令。

### 挑戰的遙遠迴響

深埋於 [TeX 的原始碼中](https://www.overleaf.com/latex/examples/typeset-the-source-code-documentation-for-tex-e-tex-or-pdftex/qkgfgyspnhcv) 有一段對實作用於表格排版的低階指令 \halign 與 \valign 主題的介紹，讀來頗令人畏懼：

> 「每當 \halign 和 \valign 能正常運作時，這都有點像奇蹟，因為它們橫跨了 TeX 許多控制結構。因此，本頁大概不是初學者開始閱讀這個程式的最佳地方；最好先掌握其他所有內容。」

Knuth 接著說

> 「請注意，在處理 \halign 時，我們會毫不猶豫地把控制權交給 TeX 的其餘部分。在關鍵時刻，會呼叫對齊例程介入並做一些小動作，但大多數時候這些例程只是潛伏在背景中。這有點像後催眠暗示。」

從這些評論來看，可以合理地推斷，即使對 Knuth 而言，實作 TeX 的表格排版也是「某種挑戰」——既要為使用者提供控制與彈性，又要同時確保 TeX 的自動表格建構演算法能與 TeX 的核心排版流程良好協調。

作者坦率承認支撐 TeX 表格排版能力的程式碼與演算法之複雜性，同時也對在相對少量、雖然密集的 Pascal（或 C）程式碼中所蘊含的龐大能力表示欽佩。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-tw/shen-ru-wen-zhang/14-how-do-tex-engines-typeset-tables.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
