使用 e-TeX 的巨集技術

使用 e-TeX 的巨集技術

e-TeX 擴充功能旨在解決 Knuth 原始 TeX 的一些缺點,並且由於 LaTeX2e 現在需要它們一段時間,因此大多數套件作者可以依賴它們的存在。現在雖然有一些資源可用於學習純 TeX 巨集習慣用法,包括這次討論在這個網站上,也可以在e-TeX 的優點總的來說,我希望看到一些具體的例子來說明 e-TeX 擴充如何讓巨集編寫者的工作變得更輕鬆。

特別是關於使用擴展和解析相關命令\protected、、\unexpanded\detokenize的一些實用建議/技巧\scantokens一些實用建議/技巧將不勝感激。它們對我來說看起來很有用,但我從未意識到什麼時候可以使用它們來簡化事情(e-TeX手冊對它們也非常簡潔)。


問題的範圍相當廣泛,但我對上面列出的擴充功能最感興趣。以下是關於其他擴充功能的一些進一步的想法,我也很樂意討論。

對於某些擴展,它們的用處對我來說是顯而易見的,包括

  • 由於每種類型的 32767 個插槽數量增加,因此不必擔心分配新暫存器
  • 方便的\numexpr\dimexpr表達式指令促進算術運算
  • \unless作為否定\if,特別是與 s 結合使用,\loop否則如果只要條件為 false 就執行循環,則必須定義新的條件
  • 各種新的追蹤命令和選項,有助於診斷

但是,有些功能讓我想知道它們是否真的被外面的包所使用,或者它們是否已經被更“現代”的方法所取代,例如

  • 混合方向排版\beginL\beginR
  • 狀態查詢,如\currentgrouptype、等\currentiftype\lastnodetype
  • 內建保存頁面頂部廢棄項目的可能性\pagediscards
  • 列出具體處罰\interlinepenalties

答案1

以 e-TeX 中的「大件」項目為例:

  • \protected\edef讓我們建立不在 an或類似的內部擴充的巨集:

    \protected\def\foo{\let\baz\bong}
    \edef\test{Some text\foo}
    

    通常會給出錯誤(假設\baz/沒有定義\bong),但這裡是“安全”的。如果你看一下 LaTeX2e\protect機制,上面是一個很多 更容易使用且更可靠:\protected絕不Expand inside x-type 定義,而使用 LaTeX2e 方法則需要\protected@edef等等。

  • \unexpanded讓我們可以保護任意令牌免於擴展,而無需使用令牌

    \edef\test{Some text\unexpanded{lots of \textbf{stuff}}}
    

    這對於任意用戶輸入非常有用。它還允許諸如

    \edef\demo{\unexpanded{tokens #}}
    

    這意味著可以輕鬆地儲存#在巨集中(請參閱expl3 tl資料類型)。

  • \detokenize有利於使東西“安全”,例如,如果它可能具有活動字符

    \csname Tokens\detokenize{&_~^\foo}\endcsname
    

    例如,如果在 LaTeX 中使用活動字元進行 UTF-8 輸入,則尤其如此

  • \numexpr等等,非常適合輕鬆進行可擴展計算

答案2

透過 grep 瀏覽 TeX Live 中的來源文件,我可以添加一些關於 e-TeX 至少在我看來不太廣泛的功能的使用的見解。

對於一些狀態查詢基元,Heiko Oberdiek 的包為其應用提供了一些說明。該atbegshi套件展示了一個巧妙的技巧,如何重新定義以盒子作為參數的原語(\shipout在本例中),同時考慮到如果要使用\setboxand截取參數\afterassignment,則在賦值後插入的標記可能會或可能不會落在盒子內,取決於盒子是否指定為asbox0或 as \hbox{...}。它看起來或多或少像這樣:

\def\shipout{%
  \edef\saved@grouplevel{\number\currentgrouplevel}
  \afterassignment\@test 
  \setbox\mybox=}

\def\@test{%
  \ifnum\saved@grouplevel<\currentgrouplevel
    \expandafter\aftergroup
  \fi
    \output
}

它使用 e-TeX\currentgrouplevel來確定是否\@test落在盒子內(打開了一個群組),在這種情況下,隨後的\output操作將推遲到盒子之後。

另一個有用的事實是,\lastnodetype對於所有不可丟棄的東西,它小於 11,如果當前清單仍然為空,則為 -1(請參閱setouterhbox這些應用程式的範例)。

正如egreg在評論中指出的那樣,\currentgrouptype可以在數學模式下查詢來決定是否使用\middle分隔符號變體,就像\currentgrouptype\left(例如這裡)。

e-TeX 的雙向排版TeX 形式的功能 - XeT 是 XeTeX 使用的功能,該bidi套件為此提供了這些功能的介面。對於一些像babel-hebrew這樣的標準 LaTeX 套件來說,這似乎是可行的方法。然而,LuaTeX 放棄了\beginL\beginR原語,而是整合了 Omega TeX 擴充。

話又說回來,對於幾個功能我還沒有找到任何實際的應用程式。它們出現的唯一地方可能是所有原語都會出現的地方,例如 LaTeX3 內核、ConTeXt MkIV 和軟體包unravel,以及作者試圖提高與使用它們的其他軟體包的兼容性的其他一些地方。這些功能包括\currentif{type,branch,level}查詢、\pagediscards功能和線路特定\{inter,club,widow}linepenalties

相關內容