
Ich schreibe eine Vorlage, die die report
Klasse verwendet und den Schriftsatz mit mehreren Paketen anpasst. Ich definiere einige Daten in einer separaten user-data.tex
Datei, die direkt danach geladen wird 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}
Diese Variablen/Konstanten werden verwendet, um zwei unterschiedliche Titelseiten bereitzustellen, die in die Fußzeile eingefügt titlesec
oder jederzeit vom Benutzer verwendet werden können.
Ist es in Ordnung, es so zu machen (nur zu verwenden \def
)? Oder sollte ich \global
, \newcommand
… oder ein anderes verwenden? Würden Sie sie in einem anderen Format als dem einfachen verwenden tex
?
\newcommand*
Nach den Kommentaren habe ich einige der Makros geändert und umbenannt:
\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}
Nach der Antwort von @Andrew verwende ich
\providecommand*\@school{No SCHOOL defined}
\newcommand*\School[1]{\renewcommand*\@school{#1}}
direkt am Anfang des Pakets, damit der Benutzer \newcommand*\@school{Something}
es entweder vor dem Laden oder \School{Something}
danach definieren kann.
Wie @barbara vermutet hat, habe ich die Vorlage dorthin verschoben, *.sty
wo ich sie als Paket lade:
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
main.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}
Es funktioniert. Der Benutzer kann den Inhalt vor dem Laden des Pakets definieren, entweder in einer separaten Datei oder zu jedem beliebigen Zeitpunkt danach mit einem „Hilfsbefehl“. Ich möchte jedoch:
-Verwenden Sie einen Befehl, um die einem Feld zugeordneten Befehle automatisch zu definieren. Neue FrageHier.
- Geben Sie dem Benutzer die Möglichkeit, das Feld beim Laden des Pakets als Option anzugeben. Ich habe es mit Folgendem versucht xkeyval
:
\define@key{fam}{thesis}[Master]{\Thesis{#1}}
\ProcessOptionsX<fam>
Ändern der Belastung in der Hauptdatei in:
\usepackage[thesis=PhD]{mypkg}
Der obige Code funktioniert, außer bei den Feldern, die mehr als ein Wort enthalten, da die Leerzeichen zwischen ihnen entfernt werden. Wie kann ich es mit z. B. zum Laufen bringen? \usepackage[title=A title with several words]{mypkg}
Ich habe es mit {A title with several words}
und versucht "A title with several words"
, aber es funktioniert nicht.
Mit dem Ansatz inDasAntwort: Ich habe jetzt diese „Factory“-Funktion, um alle Befehle auf einmal zu erstellen:
\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}} }
Antwort1
Ich habe einige (interne) Klassen, die so etwas tun. Ich definiere zunächst einen Befehl wie:
\newcommand\School[1]{\def\@school{#1}}
damit der „Benutzer“ \School{My wonderful school}
die Standardeinstellungen überschreiben kann. Intern verwendet die Klasse es, \@school
wenn der Name der Schule gedruckt werden muss.
Als nächstes lasse ich die Klasse, wenn dies sinnvoll ist, einen sinnvollen Standard für die Schule festlegen, indem ich eine Zeile wie
\School{My Wonderful School}
in der Klasse. Tatsächlich ist es wahrscheinlich die bessere Form,
\providescommand\@school{My Wonderful School}
obwohl die Verwendung des „Hilfsbefehls“ meiner Meinung nach klarer ist.
Ein Ort, an dem ich dies verwende, sind Tutorial-Arbeitsblätter, bei denen viele dieser Variablen von etwas anderem abhängen. Für diese Fälle definiere ich eine Option für die Klasse, um alle diese Variablen auf einmal festzulegen. Der „Benutzer“ beginnt seine Datei also mit
\documentclass[somecourse,solutions]{mytutorials}
und dann mytutorials.cls
habe ich drinnen
\DeclareOption{somecourse}{
\CourseName{An exciting counrse}
\Semester{Semester 2}
\CourseNumber{Math 987123}
}
\DeclareOption{solutions}{
...
}
Um alle Optionen zu verarbeiten, benötigen Sie etwas wie:
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions
Dadurch kann ich aufspringen article.cls
und Optionen übergeben, die in meiner Datei nicht definiert sind.
Schließlich möchten Sie je nach Anwendungsfall möglicherweise automatisch einen Satz von Standardwerten aus einer Datei im aktuellen Verzeichnis laden. Wenn Sie \include
oder verwenden \input
, treten Probleme auf, wenn die Datei nicht vorhanden ist. Stattdessen können Sie \@input
in Ihrer Klassendatei Folgendes verwenden:
\@input{defaults.dat}
Dadurch wird die Datei „defaults.dat“ geladen, wenn sie existiert, und andernfalls wird nichts unternommen. Diese Datei wird so wie sie ist eingebunden, daher ist die Verwendung dieses Tricks gefährlich, denn wenn die Datei Müll enthält, geht alles kaputt. Um die Fälle abzudecken, in denen diese Datei nicht existiert, müssen Sie natürlich sinnvolle Standardwerte festlegen.
(Übrigens kann es für Ihre eigenen internen Variablen wirklich nicht schaden, sie zu verwenden \def
– und es ist auch einfacher. Natürlich sollten Sie zuerst sicherstellen, dass Sie nichts anderes überschreiben!)