
Estoy escribiendo una plantilla que usa la report
clase y personaliza la composición tipográfica con varios paquetes. Estoy definiendo algunos datos en un user-data.tex
archivo separado que se carga justo después documentclass
:
\def\thesis{Master} %<PhD> or <Master>
\def\thesistitle{The title of the thesis}
\def\author{AName AFirst ASecond}
\def\authormail{[email protected]}
\def\school{Master and Doctoral School}
\def\date{City, month year}
\def\logo-university{univ.pdf}
Esas variables/constantes se utilizan para proporcionar dos páginas de título diferentes, que se incluirán en el pie de página titlesec
o que el usuario utilizará en cualquier momento.
¿Está bien hacerlo así (usando solo \def
)? ¿O debería usar \global
, \newcommand
... o cualquier otro? ¿Los colocarías en algún otro formato que no sea el simple tex
?
Después de los comentarios, cambié \newcommand*
y renombré algunas de las macros:
\newcommand*\thesis{Master} %<PhD> or <Master>
\newcommand*\thesistitle{The title of the thesis}
\newcommand*\authors{AName AFirst ASecond}
\newcommand*\authorsmail{[email protected]}
\newcommand*\school{Master and Doctoral School}
\newcommand*\titledate{City, month year}
\newcommand*\university{univ.pdf}
Después de la respuesta de @Andrew, estoy usando
\providecommand*\@school{No SCHOOL defined}
\newcommand*\School[1]{\renewcommand*\@school{#1}}
justo al comienzo del paquete, para permitir que el usuario lo defina \newcommand*\@school{Something}
antes de cargarlo o \School{Something}
después de hacerlo.
Como adivinó @barbara, moví la plantilla a una *.sty
que estoy cargando como un paquete:
mypkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mypkg}
%If not previously defined, default value applied
\providecommand*{\@mythesis}{No THESIS TYPE defined}
\providecommand*{\@myauthor}{No AUTHOR defined}
%Command to modify the field at any point after this
\newcommand*\MyThesis[1]{\renewcommand*\@mythesis{#1}}
\newcommand*\MyAuthor[1]{\renewcommand*\@myauthor{#1}}
%Command to access the field
\newcommand*\showDF[1]{\csname @#1\endcsname}
%The content may be supplied in a separate file with \Thesis
\@input{data.dat}
\endinput
principal.tex
\documentclass[a4paper,titlepage,11pt,twoside,openright]{report}
% A field may defined before loading the package
\makeatletter
\newcommand\@mythesis{My title before loading}
\makeatother
%If it not defined, the package does it
\usepackage{mypkg}
\begin{document}
% The variable may be directly accessed
\makeatletter\@mythesis\makeatother
% The content may be rewritten
\MyThesis{PhD}
% Reading with the provided command
\showDF{mythesis}
\showDF{myauthor}
\end{document}
Funciona. El usuario puede definir el contenido antes de cargar el paquete, o en un archivo separado o en cualquier momento después de hacerlo con un "comando auxiliar". Sin embargo, me gustaría:
-Utilizar un comando para definir automáticamente los comandos asociados a un campo. Nueva preguntaaquí.
-Dar al usuario la posibilidad de dar el campo como opción al cargar el paquete. Probé con xkeyval
:
\define@key{fam}{thesis}[Master]{\Thesis{#1}}
\ProcessOptionsX<fam>
cambiando la carga en el archivo principal a:
\usepackage[thesis=PhD]{mypkg}
El código anterior funciona, excepto para los campos que tienen más de una palabra, ya que se eliminan los espacios entre ellos. ¿Cómo puedo hacer que funcione con, es decir \usepackage[title=A title with several words]{mypkg}
, . Lo intenté con {A title with several words}
y "A title with several words"
pero no funciona.
Usando el enfoque enesterespuesta, ahora tengo esta función 'de fábrica' para crear todos los comandos a la vez:
\usepackage{etoolbox}
\newcommand\forcsvlistargs[2]{ \expandafter\providecommand\csname \detokenize{#1}aux\endcsname[1]{
\csname \detokenize{#1}\endcsname##1\relax}
\forcsvlist{\csname \detokenize{#1}aux\endcsname}{#2}
}
\newcommand\newDF[2]{ \expandafter\providecommand\csname th#1\endcsname{No \MakeUppercase{#2} defined}
\expandafter\newcommand\csname TH#2\endcsname[1]{\expandafter\renewcommand\csname th#1\endcsname{##1}} }
\forcsvlistargs{newDF}{{{typ}{type}}, {{date}{date}}, {{tit}{title}}, {{sch}{school}},
{{aut}{author}}, {{eaut}{eauthor}} }
Respuesta1
Tengo algunas clases (internas) que hacen algo como esto. Lo que hago es primero definir un comando como:
\newcommand\School[1]{\def\@school{#1}}
para que el "usuario" pueda utilizar \School{My wonderful school}
para sobrescribir los valores predeterminados. Internamente, la clase utiliza \@school
cada vez que necesita imprimir el nombre de la escuela.
A continuación, si esto es razonable, hago que la clase establezca un valor predeterminado razonable para la escuela al tener una línea como
\School{My Wonderful School}
en la clase. De hecho, probablemente sea mejor utilizar
\providescommand\@school{My Wonderful School}
aunque creo que usar el "comando auxiliar" es más claro.
Un lugar donde uso esto es para hojas de tutoriales donde sucede que muchas de estas variables dependen de algo más. Para estos casos, defino una opción para la clase para configurar todas estas variables de una sola vez. Entonces el "usuario" comienza su archivo con
\documentclass[somecourse,solutions]{mytutorials}
y luego dentro mytutorials.cls
tengo
\DeclareOption{somecourse}{
\CourseName{An exciting counrse}
\Semester{Semester 2}
\CourseNumber{Math 987123}
}
\DeclareOption{solutions}{
...
}
Para procesar todas las opciones necesita algo como:
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions
Esto me permite aprovechar article.cls
y pasarle opciones que no están definidas en mi archivo.
Finalmente, dependiendo de su caso de uso, es posible que desee cargar automáticamente un conjunto de valores predeterminados desde un archivo en el directorio actual. Si usa \include
o \input
, tendrá problemas cuando el archivo no exista. En su lugar, puedes usar \@input
dentro de tu archivo de clase:
\@input{defaults.dat}
Esto cargará el archivo "defaults.dat" si existe y, en caso contrario, no hará nada. Este archivo se incluirá tal cual, por lo que existe un peligro al utilizar este truco porque si el archivo contiene basura, todo se rompe. Por supuesto, para cubrir los casos en los que este archivo no existe, es necesario establecer valores predeterminados razonables.
(Por cierto, para sus propias variables internas realmente no hay ningún daño en su uso \def
, y también es más fácil. ¡Por supuesto, primero debe asegurarse de no sobrescribir nada más!)