在没有 expl3 的宏中使用可选的布尔标志

在没有 expl3 的宏中使用可选的布尔标志

我想创建一个宏\verticalStep,它将产生固定长度的垂直跳过,并采用两个可选参数negativesmall

因此你可以使用

  • \verticalStep对于标准垂直跳跃
  • \VerticalStep[negative]用于减少标准长度的垂直跳跃
  • \verticalStep[small]用于小型固定垂直箕斗
  • \VerticalStep[negative, small]通过减小标准长度来减少垂直跳跃

我一直在研究xkeyval,但pgfkeys无论如何也找不到一个简单或直接的例子来说明如何解析论证并检查选项。我设法找到了但唯一的答案是使用 expl3,我想知道是否有更优雅的解决方案,不需要切换语法

答案1

这是一个使用 的解决方案pgfkeys。该.is if处理程序允许轻松地将 PGF 键连接到\iffoobarTeX 布尔开关。

\documentclass{article}
\usepackage{pgfkeys}

\makeatletter
\newif\ifmy@verticalStep@small           % initially false
\newif\ifmy@verticalStep@negative        % initially false

\pgfkeys{
  /my@verticalStep/options/.cd,
  small/.is if=my@verticalStep@small,
  negative/.is if=my@verticalStep@negative,
}

\NewDocumentCommand \verticalStep { O{} }
  {%
    \begingroup
    \pgfkeys{/my@verticalStep/options/.cd, #1}%
    %
    \par                        % my choice
    \vspace{%
      \ifmy@verticalStep@negative -\fi
      \ifmy@verticalStep@small \smallskipamount \else \bigskipamount \fi
    }%
    \endgroup
  }
\makeatother

\setlength{\parindent}{0pt}

\begin{document}

Normal:\verticalStep
Small:\verticalStep[small]

Negative:\verticalStep[negative]
% The negative skip we just did rewound exactly one line here, because
% \baselineskip and \bigskipamount have the same natural “width” (12pt), and
% the natural width of \parskip is 0pt. That's why I do this \hspace*{4.5em},
% otherwise “Negative” would be overprinted.
\hspace*{4.5em}Negative and small:\verticalStep[negative, small]
The end.

\end{document}

在此处输入图片描述

答案2

可以非常轻松地创建像这样的简单宏expkv-cs

\ekvcSplit宏设置了一个命令,该命令接受一个强制参数(因此我们使用\NewDocumentCommand-defined 包装器来包装可选参数),并按照定义的主键的顺序将其拆分为单独的参数,以便您可以#1将其用作定义中的第一个键。可以使用它设置不直接对应于参数的其他键\ekvcSecondaryKeys(我们可以使用它来设置您的类似标志的键,然后它会将特定值转发到您的底层键)。

\documentclass{article}
\usepackage{expkv-cs}

\makeatletter
% grabbing argument as an optional argument
\NewDocumentCommand\VerticalStep{O{}}{\VerticalStep@{#1}}
\ekvcSplit\VerticalStep@
  {
     length = 0pt % value doesn't matter, will be set by ekvcChange
    ,sign = {} % empty for positive, else -
    ,star = {}
  }{\vspace#3{#2#1}}
\ekvcSecondaryKeys\VerticalStep@
  {
     nmeta negative = {sign=-}
    ,nmeta small = {length=1cm}
    ,nmeta standard = {length=2cm}
    ,nmeta force = {star=*}
  }
\ekvcChange\VerticalStep@{standard}
\makeatother

\begin{document}
abc
\VerticalStep

def
\VerticalStep[negative]

ghi
\VerticalStep[small,negative]

jkl
\VerticalStep[length=5cm]% arbitrary sizes also possible

mno
\end{document}

另一种解决方案是使用更传统的 key=value 接口,如 提供expkv-def。它使用 skip-register 来存储长度,standardsmall键改变该寄存器中的长度,并且negative-key 用作布尔值(因此可以设置为 true 或 false)。

\documentclass{article}

\usepackage{expkv-def}
\makeatletter
\ekvdefinekeys{VerticalStep}
  {
     skip    length   = \VerticalStep@length
    ,nmeta   standard = {length = 2cm}
    ,initial standard
    ,nmeta   small    = {length = 1cm}
    ,boolTF  negative = \VerticalStep@negative
  }
\ekvsetdef\VerticalStepSetup{VerticalStep}
\NewDocumentCommand\VerticalStep{O{}}
  {%
    \begingroup
      \VerticalStepSetup{#1}%
      \vspace{\VerticalStep@negative{-}{}\VerticalStep@length}%
    \endgroup
  }
\makeatother

\begin{document}
abc
\VerticalStep

def
\VerticalStep[negative]

ghi
\VerticalStep[small,negative]

jkl
\VerticalStep[length=5cm]% arbitrary sizes also possible

mno
\end{document}

两者的输出看起来相同:

在此处输入图片描述

相关内容