我想定义一个键来处理长度,但也有自定义设置。
我打算的用法:
my length = auto
将布尔值设置为 false 并忽略长度my length = half
将布尔值设置为 true,并将长度设置为0.5\linewidth
my length = 20pt
将布尔值设置为 true,并将长度设置为20pt
到目前为止一切顺利,但我想使用my length = \linewidth
或my length = \myotherlength
,例如,但使用宏*作为键会破坏.is choice
处理。
- 是的,在这种情况下是长度:)
这是我的代码:
\documentclass[12pt]{article}
\usepackage{pgfkeys}
\newif\ifisauto
\isautofalse
\newlength{\mylength}
\pgfkeys{
/my test/.cd,
my length/.is choice,
my length/auto/.code = {\isautotrue},
my length/half/.code = {\isautofalse\setlength{\mylength}{0.5\linewidth}},
my length/.unknown/.code = {\isautofalse\setlength{\mylength}{\pgfkeyscurrentname}}% won't work with macros
}
\newcommand{\printinfo}{%
\ifisauto
Choice is auto, ignoring \textbackslash mylength%
\else
Choice is not auto and \textbackslash mylength is \the\mylength%
\fi%
}
\begin{document}
Tests:
\pgfkeys{/my test/my length = auto}% OK
\printinfo
\pgfkeys{/my test/my length = half}% OK
\printinfo
\pgfkeys{/my test/my length = 20pt}% OK
\printinfo
\pgfkeys{/my test/my length = \linewidth}% this fails!
\printinfo
\end{document}
有什么想法可以使这个功能在没有布尔值和长度单独的键的情况下工作吗?
答案1
我们可以使用修改后的.is choice
处理程序来创建它(我将其称为)。与当前'.is robust choice
相比,更改包括:pgfkeys
.is choice
- 处理
.unknown
程序可以通过 直接访问未知值#1
。 - 该选择以字符串形式匹配,因此宏不会造成损害。
\documentclass[12pt]{article}
\usepackage{pgfkeys}
\newif\ifisauto
\isautofalse
\newlength{\mylength}
\makeatletter
% this is based on the definition of the .is choice handler
\pgfkeys{/handlers/.is robust choice/.code=%
\pgfkeys{%
\pgfkeyscurrentpath/.cd,%
.code=%
\edef\pgfkeys@was@choice{\unexpanded{##1}}%
\pgfkeysifdefined{\pgfkeyscurrentkey/\detokenize{##1}/.@cmd}%
{\expandafter\pgfkeysalso\expandafter{\pgfkeyscurrentkey/\detokenize{##1}}}%
{\expandafter\pgfkeysalso\expandafter{\pgfkeyscurrentkey/.unknown={##1}}},
.unknown/.code={% default .unknown handler of an .is choice
\def\pgf@marshal{\pgfkeysvalueof{/errors/unknown choice value/.@cmd}}%
{\expandafter\expandafter\expandafter\pgf@marshal\expandafter\expandafter\expandafter{\expandafter\the\expandafter\pgfkeys@pathtoks\expandafter}\expandafter{\pgfkeys@was@choice}\pgfeov}%
}%
}%
}
\makeatother
\pgfkeys{
/my test/.cd,
my length/.is robust choice,
my length/auto/.code = {\isautotrue},
my length/half/.code = {\isautofalse\setlength{\mylength}{0.5\linewidth}},
my length/.unknown/.code = {\isautofalse\setlength{\mylength}{#1}}% won't work with macros
}
\newcommand{\printinfo}{%
\ifisauto
Choice is auto, ignoring \textbackslash mylength%
\else
Choice is not auto and \textbackslash mylength is \the\mylength%
\fi%
}
\begin{document}
Tests:
\typeout{\string\pgfkeys{/my test/my length = auto}}% OK
\pgfkeys{/my test/my length = auto}% OK
\printinfo
\pgfkeys{/my test/my length = half}% OK
\printinfo
\pgfkeys{/my test/my length = 20pt}% OK
\printinfo
\pgfkeys{/my test/my length = \linewidth}% this fails!
\printinfo
\end{document}
答案2
如果不必使用,pgfkeys
您也可以使用内置所需行为的 key=value 实现,例如expkv-def
。在其中,您可以使用choice
并使用设置未知处理程序unknown-choice
。protected
只是为了制作底层键代码(否则您会在或上下文\protected
中的定义中遇到问题)。\edef
\expanded
免责声明:我是的作者expkv-def
。
\documentclass[12pt]{article}
\usepackage{expkv-def}
\newif\ifisauto
\isautofalse
\newlength{\mylength}
\ekvdefinekeys{my test}
{
protected choice my length = {
auto = \isautotrue,
half = \isautofalse\setlength\mylength{.5\linewidth}
},
protected unknown-choice my length = \isautofalse\setlength\mylength{#1}
}
\newcommand{\printinfo}{%
\ifisauto
Choice is auto, ignoring \textbackslash mylength%
\else
Choice is not auto and \textbackslash mylength is \the\mylength%
\fi%
}
\begin{document}
Tests:
\ekvset{my test}{my length = auto}% OK
\printinfo
\ekvset{my test}{my length = half}% OK
\printinfo
\ekvset{my test}{my length = 20pt}% OK
\printinfo
\ekvset{my test}{my length = \linewidth}% this fails!
\printinfo
\end{document}
答案3
由于.is choice
如果不改变一些内部代码似乎不可行,因此解决方案最终是手动进行比较。
\documentclass[12pt]{article}
\usepackage{pgfkeys}
\usepackage{ifthen}
\newif\ifisauto
\isautofalse
\newlength{\mylength}
\pgfkeys{
/my test/.cd,
my length/.code = {%
\ifthenelse{\equal{auto}{#1}}{%
\isautotrue%
}{%
\isautofalse%
\ifthenelse{\equal{half}{#1}}{%
\setlength{\mylength}{0.5\linewidth}%
}{%
\setlength{\mylength}{#1}%
}%
}%
},
}
\newcommand{\printinfo}{%
\ifisauto
Choice is auto, ignoring \textbackslash mylength%
\else
Choice is not auto and \textbackslash mylength is \the\mylength%
\fi%
}
\begin{document}
Tests:
\pgfkeys{/my test/my length = auto}% OK
\printinfo
\pgfkeys{/my test/my length = half}% OK
\printinfo
\pgfkeys{/my test/my length = 20pt}% OK
\printinfo
\pgfkeys{/my test/my length = \linewidth}% OK now
\printinfo
\pgfkeys{/my test/my length = 0.1\linewidth}% OK now
\printinfo
\pgfkeys{/my test/my length = \dimexpr \linewidth/3 - 2pt}% OK now
\printinfo
\end{document}