Как загрузить пользовательский контент для использования в шаблоне?

Как загрузить пользовательский контент для использования в шаблоне?

Я пишу шаблон, который использует reportкласс и настраивает набор текста с помощью нескольких пакетов. Я определяю некоторые данные в отдельном user-data.texфайле, который загружается сразу после 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}

Эти переменные/константы используются для предоставления двух различных титульных страниц, которые можно включить в нижний колонтитул titlesecили использовать пользователем в любое время.

Можно ли сделать это так (используя только \def)? Или мне следует использовать \global, \newcommand... или любой другой ? Вы бы разместили их в каком-либо другом формате, а не в plain tex?


После комментариев я изменил \newcommand*и переименовал некоторые макросы:

\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}

После ответа @Andrew я использую

\providecommand*\@school{No SCHOOL defined}
\newcommand*\School[1]{\renewcommand*\@school{#1}}

только в начале пакета, чтобы пользователь мог определить \newcommand*\@school{Something}его либо до загрузки, либо \School{Something}после нее.


Как и догадалась @barbara, я переместила шаблон в , *.styкоторый загружаю как пакет:

мойпакг.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

основной.текс

\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}

Это работает. Пользователь может определить содержимое до загрузки пакета, или в отдельном файле, или в любой момент после этого с помощью «вспомогательной команды». Однако я хотел бы:

-Используйте команду для автоматического определения команд, связанных с полем. Новый вопросздесь.

-Дать пользователю возможность задать поле как опцию при загрузке пакета. Я пробовал с xkeyval:

\define@key{fam}{thesis}[Master]{\Thesis{#1}}
\ProcessOptionsX<fam>

изменение загрузки в основном файле на:

\usepackage[thesis=PhD]{mypkg}

Вышеуказанный код работает, за исключением полей, которые содержат больше одного слова, так как пробелы между ними удаляются. Как мне заставить его работать с, например \usepackage[title=A title with several words]{mypkg}. Я пробовал с {A title with several words}и , "A title with several words"но это не работает.

Это не может быть сделано


Используя подход вэтотответ, теперь у меня есть эта «фабричная» функция для создания всех команд одновременно:

\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}} }

решение1

У меня есть некоторые (внутренние) классы, которые делают что-то вроде этого. Сначала я определяю команду типа:

\newcommand\School[1]{\def\@school{#1}}

так что "пользователь" может использовать \School{My wonderful school}для перезаписи значений по умолчанию. Внутри класс использует \@schoolвсякий раз, когда ему нужно напечатать название школы.

Далее, если это разумно, я заставляю класс установить разумное значение по умолчанию для школы, добавив строку типа

\School{My Wonderful School}

в классе. На самом деле, это, вероятно, лучшая форма для использования

\providescommand\@school{My Wonderful School}

хотя, я думаю, использование «вспомогательной команды» более понятно.

Одно из мест, где я это использую, — это учебные листы, где случается так, что многие из этих переменных зависят от чего-то еще. Для таких случаев я определяю опцию класса для установки всех этих переменных за один раз. Так что «пользователь» начинает свой файл с

\documentclass[somecourse,solutions]{mytutorials}

и затем внутри mytutorials.clsу меня есть

\DeclareOption{somecourse}{
  \CourseName{An exciting counrse}
  \Semester{Semester 2}
  \CourseNumber{Math 987123}
}
\DeclareOption{solutions}{
    ...
}

Для обработки всех вариантов вам понадобится что-то вроде:

\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions

Это позволяет мне использовать article.clsи передавать параметры, которые не определены в моем файле.

Наконец, в зависимости от вашего варианта использования, вы можете захотеть автоматически загрузить набор значений по умолчанию из файла в текущем каталоге. Если вы используете \includeили , \inputто вы столкнетесь с проблемами, когда файл не существует. Вместо этого вы можете использовать \@inputвнутри вашего файла класса:

\@input{defaults.dat}

Это загрузит файл "defaults.dat", если он существует, и, в противном случае, ничего не сделает. Этот файл будет включен как есть, поэтому есть опасность в использовании этого трюка, потому что если файл содержит мусор, все сломается. Конечно, чтобы охватить случаи, когда этот файл не существует, вам нужно установить разумные значения по умолчанию.

(Кстати, для ваших собственных внутренних переменных нет ничего плохого в использовании \def— и это даже проще. Конечно, сначала вам следует убедиться, что вы не перезаписываете ничего другого!)

Связанный контент