我想创建一个meta.tex
文件,模板用户将在其中填写一些常用值。我想让他在一些预定义的值中进行选择:
%meta.tex
\title{Something Fun}
\author{John Doe}
% Uncomment ONE item
\department{Foo}
%\department{Bar}
%\department{Foobar}
最好这样做:
\departments{FOO=Foo, BAR=Bar, FOOBAR=Foobar}
\department{FOO}
在 LaTeX 中实现此目的的最佳方法是什么?
在 Google 上搜索LaTeX enum
似乎不是一个明智的建议 :(
答案1
设置枚举类结构的一种相当简单的方法是通过名称包含“枚举 ID”的辅助宏。因此,如果您想让用户在 、FOO
和BAR
之间进行选择FOOBAR
,您可以定义三个内部辅助宏\nowox@enum@FOO
、\nowox@enum@BAR
、\nowox@enum@FOOBAR
。当用户选择一个枚举值时,您可以检查内部宏\nowox@enum@<user input>
是否已定义,如果已定义,则使用它(其中“使用”实际上可能意味着非常不同的事情),如果没有,则抛出错误,表明选择了无效的枚举值。
就实际使用或处理用户输入的方式和时间而言,这种方法相当灵活。在下面的示例中,每个枚举 ID 都有一个可打印的输出。用户选择的枚举的可打印输出存储在(带有\let
)通用辅助宏中。然后可以使用通用辅助宏进行排版。但完全可以考虑选择的不同用途。例如,您可以在每个枚举辅助宏中存储可执行代码,并在选择枚举时执行该代码。
该包etoolbox
用于提供命令,以\csdef
使事情变得更容易,并避免大量的\expandafter
s (\csname 和 \endcsname 到底起什么作用?,何时使用 \edef、\noexpand 和 \expandafter?)。
\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{etoolbox}
\makeatletter
% internal name for user selection
% can be given a default value
% or generate an error if not set
\newcommand*{\nowox@dep}{%
\PackageError{nowox}
{No department set}
{Choose a valid department\MessageBreak
with \string\department}}
% helper macro to typeset user-selected dep
\newcommand*{\typesetmydep}{%
\nowox@dep}
% create new enum values
% {<id>}{<value>}
\newcommand*{\mkdepartment}[1]{%
\csdef{nowox@dep@#1}}
% user command to select department from
% valid enum values
\newcommand*{\department}[1]{%
\ifcsundef{nowox@dep@#1}
{\PackageError{nowox}
{Department '#1' undefined}
{Choose a valid department}}
{\letcs\nowox@dep{nowox@dep@#1}}}
\makeatother
\mkdepartment{foo}{Dep.~of~Foo}
\mkdepartment{bar}{Dep.~of~Bar}
\department{foo}
\begin{document}
\typesetmydep
Lorem
\end{document}
答案2
如果根据“部门”而变化的只是一些文本短语:
使用最新的 LaTeX-distro,您可以通过 expl3/xparse 维护每个部门的属性列表:
\documentclass{article}
%=========================================================================================
\RequirePackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand\Departments {m} {
\keyval_parse:NNn \__MYPREAMBLECODE_prop_const_from_keyval:n \__MYPREAMBLECODE_prop_const_from_keyval:nn {#1}
}
\NewDocumentCommand\Department {m} {
\prop_if_exist:cF {\MYPREAMBLECODE_DepartmentPropertiesPrefix: #1}
{ % An error about unknown Department/unknown property list:
\msg_error:nnx {MYPREAMBLECODE} {UndefinedDepartment} {#1}
}
\cs_gset:Npx \__MYPREAMBLECODE_SelectedDepartment: {\MYPREAMBLECODE_DepartmentPropertiesPrefix: #1}
}
\msg_new:nnnn {MYPREAMBLECODE}
{UndefinedDepartment}
{\token_to_str:N\Department:\ No\ properties\ defined\ for\ Department\ `\tl_to_str:n{#1}'\ \msg_line_context: .}
{Use\ the\ command\ \token_to_str:N\Departments\ for\ specifying\ properties\ of\ Departments. }
\prop_gput:Nnn \g_msg_module_type_prop { MYPREAMBLECODE } {}
\prop_gput:Nnn \g_msg_module_name_prop { MYPREAMBLECODE } {Preamble-Code}
\NewDocumentCommand\GetSelectedDepartmentsPropertyValue{mm}{
% #1 = property
% #2 = tokens in case property is not defined
% Reasons could be:
% 1. property is not defined for the selected department.
% 2. selected department is not defined.
% 3. \Departments or \Department was not called.
% Could be a warning/error-message and/or some
% default-value.
\prop_if_exist:cTF \__MYPREAMBLECODE_SelectedDepartment: {
\prop_if_in:cnTF \__MYPREAMBLECODE_SelectedDepartment:
{#1}
{ \prop_item:cn \__MYPREAMBLECODE_SelectedDepartment: {#1} }
}{\use:n}{#2}
}
\cs_new:Nn \__MYPREAMBLECODE_prop_const_from_keyval:n {
\__MYPREAMBLECODE_prop_const_from_keyval:nn {#1}{}
}
\cs_new:Nn \__MYPREAMBLECODE_prop_const_from_keyval:nn {
\prop_const_from_keyval:cn {\MYPREAMBLECODE_DepartmentPropertiesPrefix: #1} {#2}
}
\cs_new:Nn \__MYPREAMBLECODE_SelectedDepartment: {}
\cs_new:Nn \MYPREAMBLECODE_DepartmentPropertiesPrefix: {Department:}
\ExplSyntaxOff
%=========================================================================================
\Departments{
FOO={
Property1=FOO---Property1's value,
Property2=FOO---Property2's value,
Property3=FOO---Property3's value
},
BAR={
Property1=BAR---Property1's value,
Property2=BAR---Property2's value,
Property3=BAR---Property3's value
},
FOOBAR={
Property1=FOOBAR---Property1's value,
Property2=FOOBAR---Property2's value,
Property3=FOOBAR---Property3's value
},
\empty={
Property1=[Nameless Department]---Property1's value,
Property2=[Nameless Department]---Property2's value,
Property3=[Nameless Department]---Property3's value
},
}
\Department{FOO}
%\Department{BAR}
%\Department{FOOBAR}
%\Department{}
%\Department{FOOL}
\begin{document}
\GetSelectedDepartmentsPropertyValue{Property1}{\textsf{??}}
\GetSelectedDepartmentsPropertyValue{Property2}{\textsf{??}}
\GetSelectedDepartmentsPropertyValue{Property3}{\textsf{??}}
\GetSelectedDepartmentsPropertyValue{Property4}{\textsf{??}} % Property 4 is undefined with the selected department, therefore: ??
\end{document}
(使用\Department{FOO}
相应\Department{BAR}
的\Department{FOOBAR}
命令\GetSelectedDepartmentsPropertyValue
将产生为这些部门定义的短语。
使用\Department{}
和\Department{\empty}
命令\GetSelectedDepartmentsPropertyValue
将产生为无名部门定义的短语。
使用原因 2 的\Department{FOOL}
命令总是产生\GetSelectedDepartmentsPropertyValue
⟨如果属性未定义,则使用 token⟩。