我正在尝试使用循环生成一组密钥\foreach
,但它们似乎没有正确创建。
我尝试使用显示按键的处理程序进行调试,但在我看来,它们在日志中是正确的。一定是我遗漏了什么,但我不知道是什么。
请参阅下面 MWE 中的注释,了解错误出现的位置。
梅威瑟:
\documentclass{article}
\RequirePackage{pgfkeys}
\RequirePackage{pgffor}
\RequirePackage{etoolbox}
\pgfkeys{/handlers/.store in cs/.code=\pgfkeysalso{%
\pgfkeyscurrentpath/.code=\expandafter\def\csname#1\endcsname{##1}}%
}
\pgfkeysdef{/handlers/.show path}
{%
\edef\path{\pgfkeyscurrentpath}%
\pgfkeysgetvalue{\pgfkeyscurrentpath}{\val}%
\show\path%
}
\makeatletter
\def\meide@keys{\pgfqkeys{/meide}}
\newcommand\meide@setup[3]{%
% #1 = name
% #2 = number of levels
% #3 = further key/value pairs
\meide@keys{
#1/.cd,
levels/.store in cs=meide@#1@levels,
levels=#2,
}%
\foreach \level in {0,...,\csuse{meide@#1@levels}}%
{%
\meide@setup@level{#1}{\level}%
}%
\meide@keys{#1/.cd,#3}%
}
\newcommand\meide@setup@level[2]{
% #1 = name
% #2 = level to create
\begingroup\edef\x{\endgroup\noexpand%
\meide@keys{
#1/level #2/.cd,
% uncomment the '.show path' handler to see the current keypaths. I see them as expected:
% /meide/name/level 0/myvals
% /meide/name/level 1/myvals
%myvals/.show path,
myvals/.code 2 args={%
% #1 = first
% #2 = second
\csxdef{meide@#1@myvals@level #2@first}{\unexpanded{##1}}%
\csxdef{meide@#1@myvals@level #2@second}{\unexpanded{##2}}%
}
}%
}\x%
}
% setting up one of the levels manually to show how it should work
\meide@keys{
name/level 0/myvals/.code 2 args={%
% #1 = first
% #2 = second
\csxdef{meide@name@myvals@level 0@first}{#1}%
\csxdef{meide@name@myvals@level 0@second}{#2}%
},
}
\meide@setup{name}{1}{
level 0/myvals={a}{b}, % works because it was created manually
level 1/myvals={c}{d}, % Package pgfkeys Error: I do not know the key '/meide/name/level 1/myvals', to which you passed '{c}{d}'
}
\makeatother
\begin{document}
\csuse{meide@name@myvals@level 0@first} % displays 'a'
\csuse{meide@name@myvals@level 1@first} % displays nothing
\end{document}
答案1
这不起作用,因为您的myvals/.code 2 args={...}
是一个本地分配,但它是在 TeX 组内执行的。事实上,\foreach
循环\meide@setup
在 TeX 组内执行循环代码。一旦该组完成,其中执行的所有本地定义都会自动消失。为了解决这个问题,我简单地用的宏替换了\foreach
循环,它不会在循环代码周围创建一个组。expl3
\int_step_inline:nnn
我还删除了\edef
和相关技巧,因为我不明白为什么这里需要它们。通过这两项更改,一切似乎都按预期工作。
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{expl3}
\usepackage{etoolbox}
\ExplSyntaxOn
% Borrow \int_step_inline:nnn from expl3
\cs_new_eq:NN \intstepinline \int_step_inline:nnn
\ExplSyntaxOff
\pgfkeys{/handlers/.store in cs/.code=\pgfkeysalso{%
\pgfkeyscurrentpath/.code=\expandafter\def\csname#1\endcsname{##1}}%
}
\pgfkeysdef{/handlers/.show path}
{%
\edef\path{\pgfkeyscurrentpath}%
\pgfkeysgetvalue{\pgfkeyscurrentpath}{\val}%
\show\path
}
\makeatletter
\newcommand\meide@keys{\pgfqkeys{/meide}}
\newcommand\meide@setup[3]{%
% #1 = name
% #2 = number of levels
% #3 = further key/value pairs
\meide@keys{
#1/.cd,
levels/.store in cs=meide@#1@levels,
levels=#2,
}%
\intstepinline{0}{\csuse{meide@#1@levels}}
{%
\meide@setup@level{#1}{##1}%
}%
\meide@keys{#1/.cd,#3}%
}
\newcommand\meide@setup@level[2]{%
\meide@keys{
#1/level #2/.cd,
% uncomment the '.show path' handler to see the current keypaths. I see them as expected:
% /meide/name/level 0/myvals
% /meide/name/level 1/myvals
%myvals/.show path,
myvals/.code 2 args={%
% #1 = first
% #2 = second
\csxdef{meide@#1@myvals@level #2@first}{##1}%
\csxdef{meide@#1@myvals@level #2@second}{##2}%
},
}%
}
\meide@setup{name}{1}{
level 0/myvals={a}{b}, % works
level 1/myvals={c}{d}, % now also works
}
\makeatother
\begin{document}
\csuse{meide@name@myvals@level 0@first} % displays 'a'
\csuse{meide@name@myvals@level 0@second} % displays 'b'
\csuse{meide@name@myvals@level 1@first} % displays 'c'
\csuse{meide@name@myvals@level 1@second} % displays 'd'
\end{document}
下次请尽量提供一个最简洁的例子:阅读和分析这个例子会花费太多时间。你也许可以减少代码量,尽管我知道你可能没能非常准确地找到问题所在。