堅牢なコマンドが \input 引数として展開されない

堅牢なコマンドが \input 引数として展開されない

本当に助けが必要です。私は数年間、LaTeX を気軽に使用してきましたが、詳細や問題を詳しく調べることはほとんどなく、これを理解できません。

問題

.cls私は、組織から提供された、(おそらく) 問題のある行を含むファイルで作業しています。入力されたポイント サイズの 2 番目の桁を保存するマクロを定義し、それを使用して.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: 

潜在的な解決策

問題は、 が および ではなく および を介して定義されるようにファイルを変更すると、上記のMWE.clsファイルは正常に動作し、空白の (2 ページ) PDF が生成されることにあります。@ptsize\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

何らかの不明な理由で、堅牢なマクロで取得できるはずのデータをどうしても保存する必要がある場合は、\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ε カーネルに重要な変更が導入されました。最近の変更の 1 つは、\input{...}堅牢なマクロの引数内では展開されないことです。

これらの変更は良いことであり、同時に面倒なことでもあります。良いことは、多くの点で、変更による動作方法がより厳格になったように思えることです。面倒なのは、コードをもう一度見て慣れなければならないことです。 ;-)

おそらく、組織内の他の人は、LaTeX 2ε カーネルの最近のリリースを使用していないため、LaTeX 2ε カーネルの最近のリリースで導入された変更は、彼らのマシンでの動作には影響しません。

b) この問題に対するベストプラクティスのアプローチは何でしょうか?

これらが「ベスト プラクティス」であるかどうかはわかりませんが、過去 2 年間に非常に多くの変更があったため、20 年以上にわたって慣れ親しんできた方法で LaTeX 2ε カーネル マクロに依存しなくなりました。 ;-)

特に、2 日前と同じように拡張を行う他の人が保守しているコードにはもう依存しないので、他の人のマクロに引数として渡される前に、自分のコードですべての拡張作業を行うことがよくあります。

私がこれをしないのは、変化や革新に不満を感じるからです。

これは、自分のコードをできるだけ多くの異なる LaTeX 2ε リリースと互換性を持たせるためです。

関連情報