
Estou escrevendo um modelo que usa a report
classe e personaliza a composição tipográfica com vários pacotes. Estou definindo alguns dados em um user-data.tex
arquivo separado que é carregado logo apó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}
Essas variáveis/constantes são usadas para fornecer duas páginas de título diferentes, para serem incluídas no rodapé titlesec
ou usadas pelo usuário a qualquer momento.
Posso fazer assim (usando apenas \def
)? Ou devo usar \global
, \newcommand
... ou qualquer outro? Você os colocaria em qualquer outro formato em vez de simples tex
?
Após os comentários, mudei \newcommand*
e renomeei algumas das 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}
Após a resposta de @Andrew, estou usando
\providecommand*\@school{No SCHOOL defined}
\newcommand*\School[1]{\renewcommand*\@school{#1}}
logo no início do pacote, para permitir que o usuário defina \newcommand*\@school{Something}
antes de carregá-lo ou \School{Something}
depois de fazê-lo.
Como @barbara adivinhou, movi o modelo para um *.sty
que estou carregando como um pacote:
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. O usuário pode definir o conteúdo antes de carregar o pacote, ou em um arquivo separado ou a qualquer momento após fazer isso com um 'comando auxiliar'. No entanto, eu gostaria de:
-Use um comando para definir automaticamente os comandos associados a um campo. Nova perguntaaqui.
-Dar ao usuário a possibilidade de fornecer o campo como opção ao carregar o pacote. Eu tentei com xkeyval
:
\define@key{fam}{thesis}[Master]{\Thesis{#1}}
\ProcessOptionsX<fam>
alterando o carregamento no arquivo principal para:
\usepackage[thesis=PhD]{mypkg}
O código acima funciona, exceto para os campos que possuem mais de uma palavra, já que os espaços entre eles são retirados. Como posso fazê-lo funcionar, ou seja \usepackage[title=A title with several words]{mypkg}
, . Eu tentei com {A title with several words}
e "A title with several words"
mas não funciona.
Usando a abordagem emesseresposta, agora tenho esta função 'fábrica' para criar todos os comandos de uma 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}} }
Responder1
Eu tenho algumas classes (internas) que fazem algo assim. O que faço é primeiro definir um comando como:
\newcommand\School[1]{\def\@school{#1}}
para que o "usuário" possa \School{My wonderful school}
substituir os padrões. Internamente a turma utiliza \@school
sempre que precisa imprimir o nome da escola.
Em seguida, se isso for razoável, peço à turma que defina um padrão razoável para a escola, tendo uma linha como
\School{My Wonderful School}
na aula. Na verdade, provavelmente é a melhor forma de usar
\providescommand\@school{My Wonderful School}
embora usar o "comando auxiliar" seja mais claro, eu acho.
Um lugar onde uso isso é em planilhas de tutoriais, onde muitas dessas variáveis dependem de outra coisa. Para esses casos eu defino uma opção para a classe para definir todas essas variáveis de uma só vez. Então o "usuário" inicia seu arquivo com
\documentclass[somecourse,solutions]{mytutorials}
e então dentro mytutorials.cls
eu tenho
\DeclareOption{somecourse}{
\CourseName{An exciting counrse}
\Semester{Semester 2}
\CourseNumber{Math 987123}
}
\DeclareOption{solutions}{
...
}
Para processar todas as opções você precisa de algo como:
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions
Isso me permite pegar carona article.cls
e passar opções que não estão definidas em meu arquivo.
Finalmente, dependendo do seu caso de uso, você pode querer carregar automaticamente um conjunto de padrões de um arquivo no diretório atual. Se você usar \include
ou \input
então terá problemas quando o arquivo não existir. Em vez disso, você pode usar \@input
dentro do seu arquivo de classe:
\@input{defaults.dat}
Isto irá carregar o arquivo "defaults.dat" se ele existir e, caso contrário, não fará nada. Este arquivo será incluído como está, então há um perigo em usar esse truque porque se o arquivo contiver lixo, tudo quebrará. Claro, para cobrir os casos em que este arquivo não existe, você precisa definir padrões razoáveis.
(Aliás, para suas próprias variáveis internas não há realmente nenhum mal em usar \def
- e é mais fácil também. Claro, você deve primeiro certificar-se de não estar sobrescrevendo mais nada!)