具有长度和 .is 选择的 pgfkeys

具有长度和 .is 选择的 pgfkeys

我想定义一个键来处理长度,但也有自定义设置。

我打算的用法:

  • my length = auto将布尔值设置为 false 并忽略长度
  • my length = half将布尔值设置为 true,并将长度设置为0.5\linewidth
  • my length = 20pt将布尔值设置为 true,并将长度设置为20pt

到目前为止一切顺利,但我想使用my length = \linewidthmy 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-choiceprotected只是为了制作底层键代码(否则您会在或上下文\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}

相关内容