Solución:
En primer lugar, makeatletter
es innecesario en .sty
o .cls
archivos, ya que el régimen de catcode predeterminado lo incluye; presumiblemente, esto es para alentar a los escritores de paquetes a ocultar sus macros usando @
-nombres cargados. Por esta razón, creo que usar esta El comando es inofensivo en los archivos del paquete.
Sin embargo, usando el par de comandos juntos es perjudicial, porque a diferencia de un documento, no no quiero volver a la @ = other
configuración dentro del paquete. Estos son los comandos de documentos y los pedidos estándar. makeatletter makeatother
asume que makeatother
en realidad está deshaciendo el cambio anterior, mientras que en los paquetes, es el que realiza el cambio.
Editar: Aquí hay una respuesta más informada. De acuerdo a source2e.pdf
, el siguiente esquema se utiliza para cargar paquetes y clases:
- Primero, se recopilan las opciones y demás.
- Luego, el nombre del archivo actual (es decir,
mypackage.sty
), junto con el catcode de@
, se guardan en una pila. - Luego
makeatletter
se ejecuta y, si procede, se carga el archivo solicitado. - Posteriormente, se abre la pila y se restaura el estado de carga previa al paquete.
En otras palabras, el siguiente código ignorante tiene ningún efecto en absoluto:
documentclass{article}
usepackage{bad}
begin{document}
end{document}
bad.sty:
makeatletter
makeatother
RequirePackage{unsuspecting}
Sin embargo, es muy posible que un paquete no no usar RequirePackage
, pero solo input
. En ese caso, el catcode es no protegido y, de hecho, pueden surgir errores, ya que puede comprobarse a sí mismo haciendo bad.sty
, por ejemplo:
makeatletter
makeatother
input{pgfkeys.sty}
Si eso parece artificial, eche un vistazo a pgfkeys.sty
sí mismo: es input
s pgfkeys.code.tex
, y ese archivo, a su vez, input
s pgfkeysfiltered.code.tex
. Presumiblemente, el autor se sintió seguro una vez dentro de su propio paquete, ¡pero no sospechaba que alguien más podría eludir los mecanismos de protección de carga de paquetes también!
Esto fue mucho más serio en LaTeX2.09 ya que LaTeX acababa de ejecutarse makeatletter
una vez antes de manejar todos los .sty
archivos (LaTeX2.09 no dio el .cls
/.sty
distinción). Así que era un problema común, casi una pregunta frecuente, que se lanzaran paquetes que ejecutaban makeatother
al final del archivo y trabajaron de forma aislada, pero rompieron los siguientes “archivos de estilo” (también conocidos como paquetes).
Así que una de las primeras cosas que se hizo para 2e fue restablecer el código de cat. De @
al cargar cada paquete, mantener una pila para que el código de cat se restaure al final del paquete a lo que era antes. Por lo tanto por diseño es difícil encontrar un ejemplo en el que un pícaro makeatother
al final de un paquete hace daño.
Dicho esto, es mejor no caerse que confiar en una red de seguridad.
Siempre que esté consciente de no hacer cosas malas dentro de su propio paquete (como el ejemplo de Ryan Reich), parece estar seguro dentro de los límites de lo que ofrece LaTeX.
Pero todavía los peligros acechan a la vuelta de la esquina.
Si yo digo
usepackage{afterpackage}
AfterPackage{foo}{input{bar}}
usepackage{foo}
y dentro foo.sty
makeatother
y dentro bar.tex
[email protected]baz{quux}
entonces me sale un error porque @
no es una carta (lo cual no sucede sin el makeatother
).
(el punto principal de esta respuesta es, por supuesto, que la persona (desprevenida) que usa AfterPackage
no es necesariamente el mismo que el autor del paquete)