带有 xkeyval 的库,让我的生活更轻松?

带有 xkeyval 的库,让我的生活更轻松?

这个问题与我去年提出的关于带有 xkeyval、fp 和 newcommand 的库现在图书馆已经变得相当大,添加新内容已经变得非常繁琐,而且越来越容易出错。

我现在想扩展并简化此代码,以使我的生活更轻松,并且不会破坏 fp 计算。例如,目前我只是复制粘贴代码,然后更改名称以区分各个系列(例如 RESFamilyOne、RESFamilyTwo、RESFamilyThree 等)。

\documentclass{article}
\usepackage{fp}% http://ctan.org/pkg/fp
\usepackage{xkeyval}% http://ctan.org/pkg/xkeyval
\usepackage{siunitx} %Adding SI-prefixes
\sisetup{
exponent-to-prefix = true,
round-mode         = figures,
round-precision    = 3,
scientific-notation = engineering
}%
%
%
\newcommand \Family[1]{\setkeys{RESFamily}{#1}}%
\makeatletter
%
\define@key{RESFamily}{Name}{ \newcommand \RESFamilyName{#1} }%
\define@key{RESFamily}{Value}{ \newcommand \RESFamilyValue{#1} }%
%
\makeatother
%
\AtBeginDocument{
%##################################################################################################
\Family{%
    Name = Some text here,%
    Value = ,%Value is added in the LIBRARY components
}%
%
\newcommand \defRES[3]{%START of \defRES
    \expandafter\newcommand\csname #1Name\endcsname{\csname RES#2Name\endcsname}%
    \expandafter\newcommand\csname #1Value\endcsname{#3}% 1 %
    \FPeval{#1Max}{round( \csname #1Value\endcsname * (1+20/100) :4 )}%
\ignorespaces}%END of \defRES
%
%
%LIBRARY
\defRES{Rone}{Family}{10}%
%
}%
%
\begin{document}

test = \RoneName\\
test = \RoneValue\\

\FPeval{\resultTwo}{round( 2*2 :2)}
test2 = 2 * 2 =\resultTwo\\

\FPeval{\resultThree}{round( \RoneValue * \RoneValue :2)}
test3 = \RoneValue * \RoneValue = \resultThree\\
test3a = \RoneValue * \RoneValue = \num{\resultThree}\\
%until now everything OK

test3a = \num[parse-numbers=false]{\RoneMax}\\% this offcourse works
%now NOK
test3a = \num{\RoneMax}
\FPeval{\resultFour}{round( \RoneMax * \RoneMax :2)}
test3 = \resultFour \\
test3a = \num{\resultFour}
\end{document}

问题是我可以有多个系列和键(每个最多可以有 15 个或更多),然后我需要手动指定和扩展\newcommand \RESFamilyName{#1}以模仿差异\newcommand \RESFamily**One**Name{#1}

我一直在网上搜索类似的东西,但到目前为止还没有找到,或者很可能错过了,因为我对这些“核心”内容的 Latex 知识还很陌生。

感谢您的时间和帮助。

编辑(不起作用):

\newcommand \csnshrt[2]{\csname #1#2\endcsname}%shorter \csname \endcsname
%
\newcommand \defkeyshrt{%START DEFINE@KEY-SHORT MACRO
    \foreach \n in {%
        Name,
        Address,
        City,
        Parameter,
        Whatever,
        XXX,
        YYY,
        ZZZ,
        etc,
        }{ \define@key{#1}{\n}{ \csnshrt{#1}{\n}{How To Add Value Here??} }}%\define@key{RESFamily}{Name}{ \newcommand \RESFamilyName{#1} }%
}%END DEFINE@KEY-SHORT MACRO

%USAGE
\defkeyshrt{RESFamily}%
\defkeyshrt{RESFamilyOne}%
\defkeyshrt{RESFamilyETC}%

这样define@key就会自动更改,我会在之前的位置执行一次,\defkeyshrt{RESFamily}然后我需要手动更改\define@key{RESFamily}{Name}{ \newcommand \RESFamilyName{#1} }以反映\define@key{RESFamilyETC}{Name}{ \newcommand \RESFamilyETCName{#1} }每个参数(地址、城市、无论什么、YYY,...)。

答案1

我想你想要这样的东西:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\keys_define:nn { maag/variables }
 {
  unknown .code:n = \maag_defvar:Vn \l_keys_key_tl { #1 }
 }

\NewDocumentCommand{\newfamily}{mm}
 {
  \prop_clear:N \l_maag_family_prop
  \keys_set:nn { maag/variables } { #2 }
  \prop_new:c { g_maag_family_#1_prop }
  \prop_gset_eq:cN { g_maag_family_#1_prop } \l_maag_family_prop
 }

\prop_new:N \l_maag_family_prop

\cs_new_protected:Nn \maag_defvar:nn
 {
  \prop_put:Nnn \l_maag_family_prop { #1 } { #2 }
 }
\cs_generate_variant:Nn \maag_defvar:nn { V }

\DeclareExpandableDocumentCommand{\usevar}{mm}
 {
  \prop_item:cn { g_maag_family_#1_prop } { #2 }
 }

\ExplSyntaxOff

\newfamily{FamilyOne}
 {
  Name = Gaius Iulius Caesar,
  Address = Palatinus,
  City = Roma,
  Parameter = Dictator,
  Whatever = Idae Martii,
 }

\newfamily{FamilyTwo}
 {
  Name = Iunius Brutus,
  Address = incognitum,
  City = Roma,
  Parameter = Conspirator,
  Whatever = ?,
 }

\begin{document}

\usevar{FamilyOne}{Name} was a famous guy.

\end{document}

如您所见,定义基础设施后,您只需提供新的家庭名称和家庭成员的键值对列表。

我认为,与其为每个系列中的每个键定义一个宏,不如使用一个带有两个参数的通用命令。

相关内容