上古時期的 TeX Users 都有哪些當今 TeX Users 無法想像的神級操作?
上古時期的 TeX Users 都有哪些當今 TeX Users 無法想像的神級操作?
TeX 在軟體中不算最複雜的一類,TeX 代碼相比正經的編程語言也沒那麼複雜。何況寫文檔不是打電子遊戲,所以所謂「神級操作」其實是沒有的,這種叫法也讓我感覺怪怪的。
而且,計算機軟體的發展,總體是越來越複雜的。受限於計算機性能和人們的腦洞,二三十年前人們寫的 TeX 代碼是遠沒有今天的複雜的。像 pgfplots 這種能用宏展開計算 3D 曲面圖的長達數萬行的 TeX 代碼怪獸,在過去那個排版厚一點的書就擔心內存不足的時代才是難以想像的。
技術大概有兩種,一類是從過去到現在一直在用的,基本而重要的東西;還有一類是隨時間逐漸消失,不為人所知的,那一般就是淘汰的技術。上古有而今天的人無法想像的技術,大多屬於不適應時代發展而淘汰的東西。所以在技術這方面沒必要泥古,這和武俠小說中越古老的秘籍越厲害不是一回事。─────────────────────────────────────────────
至於說要了解早期的 TeX 代碼有點什麼特別的東西,找找代碼來看看就知道了。比如說,在 Macros for The Art of Computer Programming 裡面有一小段宏,是這樣的:
ewdimenitmapsize itmapsize=10pt
{catcode`.=active
gdefitmap#1:#2:#3:#4:#5:#6&<#7&>% ems:cols:rows:-hoff:rows+voff&
{{leavevmode let.period hbox to#2itmapsize
{special{" 0 0 moveto currentpoint translate
itm@psize itm@psize scale #3 #4 true
[#1 0 0 -#1 #5 #6] {&<#7&>} imagemask}hss}}}
gdefdefineindexperiod{def.{periodparhangindent 2em }}}
defindexnoperiod{parhangindent 2em}
{catcode`p=12catcode`t=12gdefm@ff#1pt{#1}}
gdefitm@psize{expandafterm@ff heitmapsizespace}
這裡面的 itmap 就是把輸入參數作為點陣數據,直接用 special 輸出為 PostScript 代碼的點陣圖。
這個宏實際用起來是這樣的:
itmap74:1.08:72:72:-3:60% G4156
&<0003800000000000000003c00000000000000001e00000000000000000f0000000000000%
0000fc00000000000000007c00000000007000007c0000000001fc00007e0700000003fe%
00007e0f8fffffffff00007e1fc7ffffffff00007c3fe3fffffffc3ffffffff001f001f8%
1ffffffff801f001f8080000300001f000f80000003c0001f000f80000007e0001f000f8%
00e0007f0001f000f80070007f0001f000f80038007e0001f000f8003c007c0001f000f8%
001e00f80003f000f8001f00f00003e000f8000f81f00003e001f8000fc1e00003c001f8%
000fc3c00007c001f0000fc3c00007c001f0000f8780f0078003f0000f8781f80f8003f0%
00070f01fc0f0007e000000f03fe1f3f07e0ffffffffff1e3fffe07fffffffff3c07ffc0%
3c000000003800ff80000000000078007f800000000000f0003f000000000001e0003800%
01c0001c03c000200001f0001f070000000001fc003f8e0000000001ffffffcce00001e0%
01ffffffc8f80001f001f8001f00fe0003f801f8001f00fffffffc01f8001f00fffffffc%
01f8001f007c0003f801f8001f007c0003f001f8001f007c0003f001f8001f007c0003f0%
01f8001f007c0003f001f8001f007c0003f001ffffff007c0003f001ffffff007c0003f0%
01f8001f007c0003f001f8001f007c0003f001f8001f007c0003f001f8001f007c0003f0%
01f8001f007c0003f001f8001f007c0003f001f8001f007c0003f001f8001f007c0003f0%
01f8001f007c0003f001f8001f007c0003f001ffffff007c0003f001ffffff007c0003f0%
01ffffff007ffffff001f8001f007ffffff001f8001f007c0003f001f8001f007c0003f0%
01f8001f007c0003f001f8001f00fc0003f001f8000000fc0003f001f8000000fc0003c0%
&>%% Unicode char "97f6
其實就是秦九韶的「韶」字。用 Dvips 編譯出來放大點看長這樣:
&" class="content_image lazy" w="273" data-actualsrc="//i1.wp.com/pic4.zhimg.com/50/5de315faa1376e66a1ec9089d03d9cf7_hd.jpg">看到這裡就明白了,這就是個處理個別點陣字的土辦法。
這種東西當今的 TeX 用戶確實不大容易想像。不過這種代碼讀完並不會覺得這種東西是什麼神級操作。至少我當時的第一感覺就是,還不如直接一個字做一個 eps 圖片插圖呢。大鷹在邀請我回答這個問題的時候,我正在青海寧夏一帶活動,所以沒有時間來得及回答。
TeX這個語言的繁瑣之處以前也有講過不少了,和運算型語言比較,宏語言中大有trick可玩,簡單的,直接改catcode,在加上一定量的宏這樣可以在TeX中實現Basic或者Lisp的解釋器。使用expandafter以及let等的trick也有得玩,加上一些數寄存器或者dimen寄存器可以實現一些遞歸宏。對於這種可以把玩的東西,初學者使用The TeXbook即可,想要cookbook就需要看Victor Eijkhout的這本書:
&" class="content_image lazy" w="353" data-actualsrc="//i1.wp.com/pic4.zhimg.com/50/f386c6ba550c5ccf6882a2b85c902cf4_hd.jpg">這個書的時代比較早,最初在TUGboat上連載,基本上把標準的TeX82中的trick都完整覆蓋了。下載地址為:VictorEijkhout / TeX by Topic。當然,Victor Eijkhout還有本叫做The Computer Science of TeX and LaTeX的書,這個適合有一點計算機基礎的人閱讀(比如懂一點編譯原理),可見The Computer Science of TeX and LaTeX。上面提到的改catcode的,最簡單的最直觀的可以參考下面地址:Introduction to Poor Man"s Chinese TeX。即Poor Man"s 中文 TeX 簡介,中央研究院計算中心,ASPAC計畫。我當年看到這個東西的時候,真是笨的要命,一點計算機基礎都沒有,把這個文章的代碼抄下來看了半個月才明白。這種時間可以浪費,但也就適合在大學浪費了。以前的漢字編碼都是雙位元組編碼的時代,這種改catcode的方式是最簡單也最高效的,但是現在已經不怎麼完全適用了,尤其是有了Unicode之後。(順便發現了我以前寫的東西:如何快速查看 LaTeX 的宏命令的實現? - LaTeX)九十年代的漢字處理,尤其是在DOS系統之下,有著大量的點陣字體處理的場景。無論是poorman方法,CJK方法,CCT方法,中間都繞不過點陣字體。在舊的CCT之中,有個工具是專門來拼點陣生僻字的,上個月我還接觸過這一部分的內容,但是這種東西在現在基本上用不到了。這種東西說起來並不長臉,只是那個時代各種匱乏的結果。還有一個值得提一提的東西是Omega。這個東西給TeX打的補丁的長度幾乎是TeX代碼本身的長度。Omega本身有著複雜的排版功能,OTP/OCP之類能夠使它能夠處理很多複雜的語言文本。但是,這東西本身已經過時了,因為它的配置繁瑣以至於開發者都是很少的幾個人。和其他的引擎不同,比如XeTeX中控制layout engine的東西,文檔寫的清楚,寫宏來控制也不難。Omega的一部分功能,現在在LuaTeX之中還能看見,但是這些功能卻也是不痛不癢的。在繪圖技術上,以前有Xy-pic和PSTricks。但是現在基本上是幾個獨立的繪圖語言+TiKZ的天下了。一方面是這些語言以及TiKZ在設計上比較現代,在應用庫上也很豐富,加之頁面描述語言以及各種驅動宏的開發規模比較大,所以很多老的包都使用的不多了。PSTricks這個東西,就是通過special中添加PostScript代碼,最後在DVI解析的時候,把這部分代碼插到PS文件裡面,這種東西確實在九十年代比較流行,甚至有個專門處理到PS的引擎VTeX(MicroPress Home Page)。但是隨著2000年以來PDF的流行,PS的使用範圍逐漸沒落,社區裡面的PS處理工具並沒有比PDF豐富多少,或多或少都依賴GhostScript,甚至於dvips現在都不支持點陣圖文件的插圖。有個有意思的東西,比如有德國的留學生說過德國現在還有不少人在使用plain TeX,我是不太驚訝的,對於英文等等,其實plain很好用,也有一部分俄羅斯人現在也用plain TeX。在plain TeX下面想要打漢字,除了pTeX系之外,XeTeX和LuaTeX或多或少都可以進行,這都依賴於特定的包和一串特定的宏。我在2012年開始寫一些plain格式的小測試文件。自由度是很高的,當然這也僅僅是指語法,想要特定的樣式,LaTeX還是方便不少。推薦閱讀:
※學習 MetaPost 和 TikZ 這一類的 LaTeX 繪圖工具有價值嗎?
※LaTeX 如何進行 debug?
※LaTeX 命令的可選參數不能有方括弧么?
※表示內積時,應該選擇leftlangle, left< 和 langle 中的哪一個?
※有啥辦法能讓listings去檢查源代碼是不是和tex文件里一樣,而不是直接把那幾行input進來?