
Realmente me vendría bien un poco de ayuda: he estado usando LaTeX de manera casual durante varios años, pero rara vez he tenido que profundizar en los detalles o problemas, y no puedo resolver esto.
Problema
Estoy trabajando con un .cls
archivo que me proporcionó mi organización y que tiene una línea (posiblemente) problemática. Define una macro que almacena el segundo dígito del tamaño en puntos ingresado y luego lo usa para ingresar un .clo
archivo. Un MWE emparejado es el siguiente:
\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}
También creé un .tex
archivo MWE para compilar:
\documentclass[11pt]{mwe}
\begin{document}
\end{document}
Sin embargo, cuando compilo esto usando latexmk -synctex=1 -interaction=nonstopmode -file-line-error -pdf -outdir=%OUTDIR% %DOC%
(dentro de VSCode usando LaTeX Workshop), aparece este archivo de registro con un mensaje que dice
`File `[email protected]' not found`
El registro dice:
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:
Solucion potencial
Aquí está la cuestión: si cambio el .cls
archivo para que @ptsize
se defina vía \newcommand
y \renewcommand
en lugar de vía \newrobustcmd
y \renewrobustcmd
, entonces el MWE anterior.tex
funciona bien y genera un PDF en blanco (de dos páginas).
¿Alguien podría a) explicar por qué sucede esto (hasta donde yo sé, este .cls
archivo funciona bien para otras personas de mi organización) y b) cuál sería el enfoque de mejores prácticas para este problema? ¡Gracias de antemano!
Respuesta1
La diferencia de comportamiento se puede ver en este código de ejemplo:
\makeatletter
\protected\def\@ptsize{1}
\input{size1\@ptsize.clo}
\stop
que solía ingresar size11.clo
, pero desde la versión de LaTeX del 1 de octubre de 2020 ya no lo hace, sino que genera un error con:
! 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:
Este fue un cambio deliberado en el mecanismo de análisis de nombres de archivos de LaTeX. Fue reemplazado por un analizador más robusto que no expande las macros protegidas (junto con varias otras ventajas). El comportamiento del nuevo analizador es el correcto respecto a macros robustas: estasno puedofuncionan en contextos de solo expansión porque se romperán de una forma u otra (tú poder encontrar montones de ejemplos de eso alrededor), por lo que no ampliarlos es lo razonable.
El archivo de clase de su organización hace un mal uso de comandos robustos para almacenar algunos datos (lo que normalmente llamamos una "lista de tokens"). Datos como ese en su mayoría siempre tienen que estar disponibles para otras macros, por lo que tienen que expandirse, por lo que no pueden ser robustos/protegidos. Lo correcto, si puede editar el archivo de clase, es reemplazarlo \(re)newrobustcmd
por \(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}
Para que conste, el mensaje de error
! LaTeX Error: File `[email protected]' not found.
Se ve así porque el analizador de nombres de archivos funciona con \escapechar=-1
, luego \@ptsize
se activa \string
y se convierte en @ptsize
.
Respuesta2
Si por alguna oscura razón se insiste en almacenar datos que deberían ser recuperables en macros robustas, entonces usted mismo puede desencadenar la expansión y colocar los tokens en el orden correcto, utilizando algún \expandafter
// \romannumeral
truco de intercambio de argumentos:
archivo 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%
}
En mi sistema compilando un archivo test.tex
:
\documentclass{mwe}
\stop
produce esta salida de consola:
$ 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.
y este archivo 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 tus preguntas:
a) explicar por qué sucede esto (hasta donde yo sé, este archivo .cls funciona bien para otras personas de mi organización)
Se introdujeron cambios significativos en el kernel LaTeX 2ε. Uno de los cambios más recientes es que dentro del argumento de \input{...}
las macros robustas no se amplía.
Estos cambios son buenos y molestos al mismo tiempo: son buenos porque en muchas cosas la forma en que funcionan ahora me parece más estricta. Son molestos porque tengo que volver a mirar el código y acostumbrarme. ;-)
Probablemente las otras personas de su organización no utilicen una de las versiones más recientes del kernel LaTeX 2ε y, por lo tanto, los cambios introducidos con las versiones más recientes del kernel LaTeX 2ε no afectan la forma en que funcionan las cosas en sus máquinas. .
b) ¿cuál sería el enfoque de mejores prácticas para este problema?
No sé si estas son "mejores prácticas", pero como ha habido tantos cambios en los últimos dos años, dejé de depender de las macros del kernel LaTeX 2ε para trabajar como estaba acostumbrado durante más de dos décadas. ;-)
Especialmente, ya no confío en el código mantenido por otros que realizan la expansión de la misma manera que lo hizo hace dos días y, por lo tanto, a menudo hago que mi propio código haga todo el trabajo de expansión antes de que las cosas se entreguen como argumentos a las macros de otras personas.
No hago esto porque no estaría contento con los cambios e innovaciones.
Lo hago para que mi propio código sea compatible con tantas versiones diferentes de LaTeX 2ε como sea posible.