
我確實需要一些幫助 - 我已經隨意使用 LaTeX 好幾年了,但很少需要深入研究細節或問題,而且我無法弄清楚這一點。
問題
我正在處理.cls
我的組織給我的一個文件,其中有一個(可能)有問題的行。它定義了一個宏,用於儲存輸入的點大小的第二位數字,然後使用它來輸入檔案.clo
。配對的 MWE 如下:
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{mwe}
\RequirePackage{etoolbox}
\newrobustcmd\@ptsize{}
\DeclareOption{10pt}{\renewrobustcmd\@ptsize{0}}
\DeclareOption{11pt}{\renewrobustcmd\@ptsize{1}}
\DeclareOption{12pt}{\renewrobustcmd\@ptsize{2}}
\ExecuteOptions{11pt}
\ProcessOptions
\input{size1\@ptsize.clo}
我還創建了一個 MWE.tex
檔案來編譯:
\documentclass[11pt]{mwe}
\begin{document}
\end{document}
但是,當我使用(在 VSCode 內使用 LaTeX Workshop)編譯此文件時latexmk -synctex=1 -interaction=nonstopmode -file-line-error -pdf -outdir=%OUTDIR% %DOC%
,我收到此日誌文件,其中包含一條訊息:
`File `[email protected]' not found`
日誌說:
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (MiKTeX 20.11) (preloaded format=pdflatex 2020.11.3) 3 NOV 2020 08:57
entering extended mode
**"path/to/mwe/mwe.tex"
("path/to/mwe/mwe.tex"
LaTeX2e <2020-10-01> patch level 2
L3 programming layer <2020-10-27> xparse <2020-03-03> ("path/to\mwe\mwe.cls" <-- In case it matters, these slashes
Document Class: mwe really do switch directions
(path\to\tex/latex/etoolbox\etoolbox.sty <-- Here as well
Package: etoolbox 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count175
)
! LaTeX Error: File `[email protected]' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: clo)
Enter file name:
潛在的解決方案
事情是這樣的:如果我更改文件.cls
,以便透過and而不是透過and@ptsize
定義,那麼上面的 MWE文件就可以正常工作,產生一個空白(兩頁)PDF。\newcommand
\renewcommand
\newrobustcmd
\renewrobustcmd
.tex
任何人都可以a)解釋為什麼會發生這種情況(據我所知,這個.cls
文件對於我組織中的其他人來說工作得很好),b)解決這個問題的最佳實踐方法是什麼?先感謝您!
答案1
在此範例程式碼中可以看到行為上的差異:
\makeatletter
\protected\def\@ptsize{1}
\input{size1\@ptsize.clo}
\stop
它曾經用於輸入size11.clo
,但自 2020-10-01 LaTeX 發布以來,它不再輸入,而是出現錯誤:
! LaTeX Error: File `[email protected]' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: clo)
Enter file name:
這是 LaTeX 的檔名解析機制的有意改變。它被一個更強大的解析器所取代,該解析器不會擴展受保護的巨集(以及其他一些好東西)。新解析器的行為對於健壯的巨集來說是正確的:這些不能在僅擴展上下文中工作,因為它們會以某種方式破壞(你 能 尋找 噸 的 例子 的 那 大約),所以不擴展它們是合理的做法。
您組織中的類別文件濫用強大的命令來儲存一些資料(我們通常稱為「令牌清單」)。像這樣的資料通常必須可供其他巨集使用,因此它必須擴展,因此它不能是健壯的/受保護的。如果您可以編輯類文件,正確的做法是將替換\(re)newrobustcmd
為\(re)newcommand
:
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{mwe}
\RequirePackage{etoolbox}
\newcommand\@ptsize{}
\DeclareOption{10pt}{\renewcommand\@ptsize{0}}
\DeclareOption{11pt}{\renewcommand\@ptsize{1}}
\DeclareOption{12pt}{\renewcommand\@ptsize{2}}
\ExecuteOptions{11pt}
\ProcessOptions
\input{size1\@ptsize.clo}
作為記錄,錯誤訊息
! LaTeX Error: File `[email protected]' not found.
看起來像這樣,因為檔案名稱解析器與 一起工作\escapechar=-1
,然後\@ptsize
與 一起工作\string
並成為@ptsize
。
答案2
如果出於某種模糊的原因,堅持儲存應該在健壯的巨集中檢索的數據,那麼您可以使用一些 //argument-exhaving-trickery 來觸發擴展並自行放置令牌的正確\expandafter
順序\romannumeral
:
文件mwe.cls
:
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{mwe}
\RequirePackage{etoolbox}
\newrobustcmd\@ptsize{}
\DeclareOption{10pt}{\renewrobustcmd\@ptsize{0}}
\DeclareOption{11pt}{\renewrobustcmd\@ptsize{1}}
\DeclareOption{12pt}{\renewrobustcmd\@ptsize{2}}
\newcommand\exchangeargs[2]{#2#1}
\ExecuteOptions{11pt}
\ProcessOptions
% It is not relied on \input expanding and putting into correct order
% tokens of its argument.
% Instead \romannumeral-expansion brings all tokens into
% correct order before \input and \input's filename-parsing
% come into action.
% (This way things might sustain more changes to \input's
% filename-parsing.)
\expandafter\input\expandafter{%
\romannumeral
\expandafter\exchangeargs\expandafter{\@ptsize}{\z@ size1}.clo%
}
在我的系統上編譯檔案test.tex
:
\documentclass{mwe}
\stop
產生這個控制台輸出:
$ pdflatex test.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./test.tex
LaTeX2e <2020-10-01> patch level 2
L3 programming layer <2020-10-27> xparse <2020-03-03> (./mwe.cls
Document Class: mwe
(/usr/local/texlive/2020/texmf-dist/tex/latex/etoolbox/etoolbox.sty)
(/usr/local/texlive/2020/texmf-dist/tex/latex/base/size11.clo)) )
No pages of output.
Transcript written on test.log.
和這個文件test.log
:
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=pdflatex 2020.11.23) 4 DEC 2020 19:47
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
**test.tex
(./test.tex
LaTeX2e <2020-10-01> patch level 2
L3 programming layer <2020-10-27> xparse <2020-03-03> (./mwe.cls
Document Class: mwe
(/usr/local/texlive/2020/texmf-dist/tex/latex/etoolbox/etoolbox.sty
Package: etoolbox 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count175
)
(/usr/local/texlive/2020/texmf-dist/tex/latex/base/size11.clo
File: size11.clo 2020/04/10 v1.4m Standard LaTeX file (size option)
)) )
Here is how much of TeX's memory you used:
364 strings out of 479485
4393 string characters out of 5871962
273140 words of memory out of 5000000
17462 multiletter control sequences out of 15000+600000
535388 words of font info for 30 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191
52i,1n,59p,208b,36s stack positions out of 5000i,500n,10000p,200000b,80000s
No pages of output.
PDF statistics:
0 PDF objects out of 1000 (max. 8388607)
0 named destinations out of 1000 (max. 500000)
1 words of extra memory for PDF output out of 10000 (max. 10000000)
對於您的問題:
a) 解釋為什麼會發生這種情況(據我所知,這個 .cls 檔案對於我組織中的其他人來說運作得很好)
LaTeX 2ε 核心發生了重大變化。最近的變化之一是,在強健宏的參數內\input{...}
沒有擴展。
這些變化是好的,但同時也很煩人:它們是好的,因為在很多事情上,他們現在的工作方式對我來說似乎更嚴格。它們很煩人,因為我必須再次查看程式碼並習慣它。 ;-)
您組織中的其他人可能不使用 LaTeX 2ε-kernel 的最新版本之一,因此 LaTeX 2ε-kernel 的最新版本引入的變更不會影響其電腦上的工作方式。
b) 解決這個問題的最佳實務方法是什麼?
我不知道這些是否是“最佳實踐”,但由於過去兩年發生瞭如此多的變化,我已經不再依賴 LaTeX 2ε-內核宏來按照我二十多年來習慣的方式工作。 ;-)
特別是,我不再像兩天前那樣依賴其他人維護的程式碼進行擴展,因此我經常讓自己的程式碼在將東西作為參數傳遞給其他人的巨集之前完成所有擴展工作。
我不這麼做是因為我會對這些變化和創新感到不滿。
我這樣做是為了讓我自己的程式碼與盡可能多的不同 LaTeX 2ε 版本相容。