我正在建立一个项目目录,并希望确保我的字段始终按特定顺序显示(为了论证的目的,我们按“意图编号、重量、直径”的顺序显示)即使我以不同的顺序输入数据。我想按照我定义键的顺序而不是输入键的顺序显示。这可以吗?
\documentclass{article}
\usepackage{keyval}
\newcommand{\catalogueentry}[1]{\setkeys{entrydetails}{#1}}
\makeatletter
\define@key{entrydetails}{intentorynumber}{\noindent \textbf{Intentory number:} \emph{#1}\\}
\define@key{entrydetails}{weight}{\noindent \textbf{Weight:} \emph{#1}\\}
\define@key{entrydetails}{diameter}{\noindent \textbf{Diameter:} \emph{#1}\\}
\makeatother
\begin{document}
\catalogueentry{intentorynumber=0001,
diameter= very small,
weight=really heavy,
}
\end{document}
答案1
键值接口的基本功能不仅仅是提供键并为其分配一些值,而且还存储键值并在稍后处理(比如说排版)它们的值。
您应该像往常一样,将定义数据和处理数据分开。
该\setkeys
宏用于识别键(给出了哪一个?)并将它们存储到\KV...
宏. Those values can be used arbitrarily often inside the
catalogueentry 命令中,以便对它们执行一些(奇怪的)事情。
\documentclass{article}
\usepackage{keyval}
\newcommand{\catalogueentry}[1]{%
\setkeys{entrydetails}{#1}
\noindent \textbf{Intentory number:} \emph{\KVIntentoryNumber}
\noindent \textbf{Weight:} \emph{\KVWeight}
\noindent \textbf{Diameter:} \emph{\KVDiameter}
}
\makeatletter
\define@key{entrydetails}{intentorynumber}{\def\KVIntentoryNumber{#1}}
\define@key{entrydetails}{weight}{\def\KVWeight{#1}}
\define@key{entrydetails}{diameter}{\def\KVDiameter{#1}}
\makeatother
\begin{document}
\catalogueentry{intentorynumber=0001,
diameter= very small,
weight=really heavy,
}
\catalogueentry{intentorynumber=0002,
weight={${2\times 10^{30}\;}$ kg}, % Sorry Joseph, no \SI... here :-P
diameter= very large
}
\end{document}
更新
只要不涉及分组,键值宏就是全局的,即从外部命令的一次调用到下一次调用的内容,值会一直存在,除非被新的规范覆盖。
这可以通过分组来改变。
无论如何(第一版中没有这个):如果根本没有给出键,则不会定义相关的键宏,并且调用\KV...
将失败。使用\ifdef{\KV...}{true branch}{false branch}
将防止这种情况发生。
\documentclass{article}
\usepackage{keyval}
\usepackage{siunitx} % Just to make Joseph Wright happy :-P
\usepackage{etoolbox}
\newcommand{\catalogueentry}[1]{%
\begingroup
\setkeys{entrydetails}{#1}
\ifdef{\KVIntentoryNumber}{%
\noindent \textbf{Intentory number:} \emph{\KVIntentoryNumber} %
}{}%
\ifdef{\KVWeight}{%
\noindent \textbf{Weight:} \emph{\KVWeight}%
}{}%
\ifdef{\KVDiameter}{%
\noindent \textbf{Diameter:} \emph{\KVDiameter}%
}{}%
\endgroup
}
\makeatletter
\define@key{entrydetails}{intentorynumber}{\def\KVIntentoryNumber{#1}}
\define@key{entrydetails}{weight}{\def\KVWeight{#1}}
\define@key{entrydetails}{diameter}{\def\KVDiameter{#1}}
\makeatother
\begin{document}
\catalogueentry{intentorynumber=0001,
diameter= very small,
weight=really heavy,
}
\catalogueentry{intentorynumber=0002,
weight={\SI{2d30}{kg}},
diameter= very large
}
\catalogueentry{intentorynumber=0003,
diameter={\SI{13.7d9}{ly}}
}
\end{document}
答案2
这个想法与其他优秀答案相同,但我更喜欢expl3
样式键值语法。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\catalogueentry}{m}
{
\group_begin:
\keys_set:nn { tuthmoses/catalogue } { #1 }
\tuthmoses_catalogue_entry:VVV
\l_tuthmoses_inventory_tl
\l_tuthmoses_weight_tl
\l_tuthmoses_diameter_tl
\group_end:
}
\keys_define:nn { tuthmoses/catalogue }
{
inventorynumber .tl_set:N = \l_tuthmoses_inventory_tl,
weight .tl_set:N = \l_tuthmoses_weight_tl,
diameter .tl_set:N = \l_tuthmoses_diameter_tl,
inventorynumber .initial:n = \tuthmoses_error:n { Inventory~number },
weight .initial:n = \tuthmoses_error:n { Weight },
diameter .initial:n = \tuthmoses_error:n { Diameter },
}
\cs_new_protected:Nn \tuthmoses_catalogue_entry:nnn
{
\par\noindent
\textbf{Inventory~Number:} ~ #1 \\*
\textbf{Weight:} ~ #2 \\*
\textbf{Diameter:} ~ #3
\par
}
\cs_generate_variant:Nn \tuthmoses_catalogue_entry:nnn { VVV }
\cs_new_protected:Nn \tuthmoses_error:n
{
\msg_error:nnn { tuthmoses/catalogue } { Missing~value } { #1 }
}
\msg_new:nnnn { tuthmoses/catalogue } { Missing~value }
{
Missing~value~for~#1
}
{
You~must~specify~a~value~for~#1
}
\ExplSyntaxOff
\begin{document}
\catalogueentry{
inventorynumber=0001,
diameter= very small,
weight=really heavy,
}
\catalogueentry{
diameter= very small,
inventorynumber=0002,
weight=really heavy,
}
\catalogueentry{
diameter= very small,
weight=really heavy,
}
\end{document}
主命令打开一个组来对本地值进行更改;然后它从参数中设置键并使用将\tuthmoses_catalogue_entry:VVV
值存储为参数的变量的函数。
接下来我们定义键及其初始值,这将引发错误。
主内部函数使用#1
、#2
和进行排版#3
;它的变体被定义为使用变量而不是显式参数。
最后定义了错误报告函数;它本质上是的语法糖\msg_error:nnn
。实际的错误消息结束了代码部分。
输出
错误输入的错误消息
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! tuthmoses/catalogue error: "Missing value"
!
! Missing value for Inventory number
!
! See the tuthmoses/catalogue documentation for further information.
!
! For immediate help type H <return>.
!...............................................
l.70 }
? h
|'''''''''''''''''''''''''''''''''''''''''''''''
| You must specify a value for Inventory number
|...............................................