
Ich könnte wirklich Hilfe gebrauchen – ich verwende LaTeX seit mehreren Jahren gelegentlich, musste mich aber selten mit den Details oder Problemen befassen, und ich komme nicht dahinter.
Problem
Ich arbeite mit einer .cls
Datei, die ich von meiner Organisation erhalten habe und die eine (möglicherweise) problematische Zeile enthält. Sie definiert ein Makro, das die zweite Ziffer der eingegebenen Punktgröße speichert und diese dann zur Eingabe einer .clo
Datei verwendet. Ein verkürztes MWE lautet wie folgt:
\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}
Ich habe auch eine MWE- .tex
Datei zum Kompilieren erstellt:
\documentclass[11pt]{mwe}
\begin{document}
\end{document}
Wenn ich dies jedoch kompiliere latexmk -synctex=1 -interaction=nonstopmode -file-line-error -pdf -outdir=%OUTDIR% %DOC%
(innerhalb von VSCode mit LaTeX Workshop), erhalte ich diese Protokolldatei mit der Meldung
`File `[email protected]' not found`
Im Protokoll steht:
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:
Mögliche Lösung
So ist es: Wenn ich die .cls
Datei so ändere, dass „über“ und statt „über “ und @ptsize
definiert ist , funktioniert die obige MWE- Datei einwandfrei und erzeugt eine leere (zweiseitige) PDF-Datei.\newcommand
\renewcommand
\newrobustcmd
\renewrobustcmd
.tex
Könnte irgendjemand a) erklären, warum das passiert (soweit ich weiß, .cls
funktioniert diese Datei bei anderen Leuten in meiner Organisation einwandfrei) und b) was der Best-Practice-Ansatz für dieses Problem wäre? Vielen Dank im Voraus!
Antwort1
Der Unterschied im Verhalten ist in diesem Beispielcode zu sehen:
\makeatletter
\protected\def\@ptsize{1}
\input{size1\@ptsize.clo}
\stop
Dies hat früher eingegeben size11.clo
, aber seit der LaTeX-Version vom 01.10.2020 ist dies nicht mehr der Fall, stattdessen werden folgende Fehler ausgegeben:
! 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:
Dies war eine bewusste Änderung im Dateinamen-Parsing-Mechanismus von LaTeX. Er wurde durch einen robusteren Parser ersetzt, der geschützte Makros nicht erweitert (und einige andere Vorteile bietet). Das Verhalten des neuen Parsers ist in Bezug auf robuste Makros korrekt: Diesekann nichtfunktionieren nur in Erweiterungskontexten, da sie auf die eine oder andere Weise kaputt gehen (Du dürfen finden Tonnen von Beispiele von Das um), daher ist es vernünftig, sie nicht auszuweiten.
Die Klassendatei in Ihrer Organisation missbraucht robuste Befehle, um einige Daten zu speichern (was wir normalerweise als „Token-Liste“ bezeichnen). Solche Daten müssen meistens immer für andere Makros verfügbar sein, müssen also erweitert werden und können daher nicht robust/geschützt sein. Wenn Sie die Klassendatei bearbeiten können, ist es am besten, sie \(re)newrobustcmd
durch Folgendes zu ersetzen \(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}
Zur Erinnerung: Die Fehlermeldung
! LaTeX Error: File `[email protected]' not found.
sieht so aus, weil der Dateinamenparser mit arbeitet \escapechar=-1
, dann \@ptsize
mit getroffen wird \string
und zu wird @ptsize
.
Antwort2
Wenn aus irgendeinem unklaren Grund darauf bestanden werden soll, Daten, die abrufbar sein sollen, in robusten Makros zu speichern, dann können Sie die Erweiterung und Platzierung der Token in der richtigen Reihenfolge selbst auslösen, indem Sie einige \expandafter
/ \romannumeral
/Argument-Austauschtricks anwenden:
Datei 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%
}
Auf meinem System wird eine Datei kompiliert test.tex
:
\documentclass{mwe}
\stop
ergibt diese Konsolenausgabe:
$ 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.
und diese Datei 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)
Zu Ihren Fragen:
a) erklären, warum das passiert (soweit ich weiß, funktioniert diese CLS-Datei bei anderen Leuten in meiner Organisation einwandfrei)
Es wurden wesentliche Änderungen am LaTeX 2ε-Kernel vorgenommen. Eine der neueren Änderungen besteht darin, dass innerhalb des Arguments von \input{...}
robust keine Makros erweitert werden.
Diese Änderungen sind gut und ärgerlich zugleich: Sie sind gut, weil mir die neue Arbeitsweise bei vielen Dingen stringenter vorkommt. Sie sind ärgerlich, weil ich mir den Code nochmal anschauen und mich daran gewöhnen muss. ;-)
Die anderen Personen in Ihrer Organisation verwenden wahrscheinlich keine der neueren Versionen des LaTeX 2ε-Kernels, und daher haben die mit den neueren Versionen des LaTeX 2ε-Kernels eingeführten Änderungen keinen Einfluss auf die Funktionsweise ihrer Rechner.
b) Was wäre der Best-Practice-Ansatz für dieses Problem?
Ich weiß nicht, ob das die „Best Practices“ sind, aber da es in den letzten zwei Jahren so viele Änderungen gab, verlasse ich mich nicht mehr darauf, dass LaTeX 2ε-Kernel-Makros so funktionieren, wie ich es über zwei Jahrzehnte gewohnt war. ;-)
Insbesondere verlasse ich mich bei Erweiterungen nicht mehr auf die gleiche Weise wie noch vor zwei Tagen auf von anderen gepflegten Code und lasse daher häufig die gesamte Erweiterungsarbeit von meinem eigenen Code erledigen, bevor die Dinge als Argumente an die Makros anderer Leute übergeben werden.
Ich mache das nicht, weil ich mit den Änderungen und Neuerungen unzufrieden wäre.
Ich tue dies, um meinen eigenen Code mit so vielen verschiedenen LaTeX 2ε-Versionen wie möglich kompatibel zu machen.