Robuster Befehl, der nicht als \ input-Argument erweitert wird

Nov 03 2020

Ich könnte wirklich Hilfe gebrauchen - ich benutze LaTeX seit mehreren Jahren beiläufig, musste mich aber selten mit Details oder Problemen befassen, und ich kann das nicht herausfinden.

Problem

Ich arbeite mit einer .clsDatei, die mir von meiner Organisation gegeben wurde und die eine (möglicherweise) problematische Linie hat. Es definiert ein Makro, das die zweite Ziffer der eingegebenen Punktgröße speichert und diese dann zur Eingabe einer .cloDatei verwendet. Ein gepaarter MWE ist 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- .texDatei zum Kompilieren erstellt:

\documentclass[11pt]{mwe}

\begin{document}
    
\end{document}

Wenn ich dies jedoch mit 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`

Das Protokoll sagt:

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

Hier ist die Sache: Wenn ich die .clsDatei so ändere , dass @ptsizesie über \newcommandund \renewcommandanstelle von \newrobustcmdund definiert ist \renewrobustcmd, .texfunktioniert die obige MWE- Datei einwandfrei und generiert ein leeres (zweiseitiges) PDF.

Könnte jemand a) erklären, warum dies geschieht (soweit ich weiß, .clsfunktioniert diese Datei für andere Personen in meiner Organisation einwandfrei) und b) wie die Best-Practice-Vorgehensweise für dieses Problem aussehen würde? Danke im Voraus!

Antworten

4 PhelypeOleinik Nov 04 2020 at 19:49

Der Unterschied im Verhalten ist in diesem Beispielcode zu sehen:

\makeatletter
\protected\def\@ptsize{1}
\input{size1\@ptsize.clo}
\stop

die früher eingegeben hat size11.clo, aber seit der LaTeX-Version 2020-10-01 nicht mehr, sondern Fehler mit:

! 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 absichtliche Änderung des Analysemechanismus für LaTeX-Dateinamen. Es wurde durch einen robusteren Parser ersetzt, der geschützte Makros (zusammen mit mehreren anderen Extras) nicht erweitert. Das Verhalten des neuen Parser ist die richtige bezüglich robust Makros: diese nicht , kann in expansions nur Kontexten arbeiten , weil sie eine Art und Weise brechen oder eine andere ( Sie können finden Tonnen von Beispielen von dieser um ), so sie nicht erweitert ist die vernünftige Sache machen.

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, daher müssen sie erweitert werden und können daher nicht robust / geschützt sein. Das Richtige zu tun, wenn Sie die Klassendatei bearbeiten können , ist zu ersetzen \(re)newrobustcmddurch \(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}

Für den Datensatz die Fehlermeldung

! LaTeX Error: File `[email protected]' not found.

sieht so aus, weil der Dateinamen-Parser mit arbeitet \escapechar=-1, dann \@ptsizemit getroffen wird \stringund wird @ptsize.

2 UlrichDiez Dec 05 2020 at 02:00

Wenn aus irgendeinem unbekannten Grund darauf bestanden werden soll, Daten zu speichern, die in robusten Makros abrufbar sein sollten, können Sie die Erweiterung auslösen und die Token selbst in der richtigen Reihenfolge platzieren, indem Sie einige \expandafter/ \romannumeral/ Argumente austauschen:

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 beim Kompilieren einer Datei 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)

Auf Ihre Fragen:

a) Erklären Sie, warum dies geschieht (soweit ich weiß, funktioniert diese .cls-Datei für andere Personen in meiner Organisation einwandfrei).

Der LaTeX 2ε-Kernel wurde erheblich verändert. Eine der jüngsten Änderungen ist, dass innerhalb des Arguments \input{...}robuste Makros nicht erweitert werden.

Diese Änderungen sind gleichzeitig gut und ärgerlich: Sie sind gut, weil mir bei vielen Dingen die Art und Weise, wie sie jetzt funktionieren, strenger erscheint. Sie sind nervig, weil ich mir den Code noch einmal ansehen und mich daran gewöhnen muss. ;-);

Wahrscheinlich verwenden die anderen Personen in Ihrer Organisation keine der neueren Versionen des LaTeX 2ε-Kernels. Daher wirken sich Änderungen, die mit neueren Versionen des LaTeX 2ε-Kernels eingeführt wurden, nicht auf die Funktionsweise ihrer Computer aus .

b) Was wäre der Best-Practice-Ansatz für dieses Problem?

Ich weiß nicht, ob dies "Best Practices" sind, aber da es in den letzten zwei Jahren so viele Änderungen gegeben hat, habe ich aufgehört, mich auf LaTeX 2ε-Kernel-Makros zu verlassen, um so zu arbeiten, wie ich es über zwei Jahrzehnte gewohnt war. ;-);

Insbesondere verlasse ich mich nicht mehr auf Code, der von anderen verwaltet wird, die Erweiterungen auf die gleiche Weise wie vor zwei Tagen ausführen, und deshalb lasse ich oft meinen eigenen Code die gesamte Erweiterungsarbeit erledigen, bevor die Dinge als Argumente an die Makros anderer übergeben werden.

Ich mache das nicht, weil ich über die Veränderungen und Innovationen unglücklich wäre.

Ich mache dies, um meinen eigenen Code mit so vielen verschiedenen LaTeX 2ε-Releases wie möglich kompatibel zu machen.