如何定义具有等效布尔值键的 key=value

如何定义具有等效布尔值键的 key=value

假设您正在align为某些环境定义一个 key=value realign,您将按以下方式使用:

\usepackage{xkeyval}% http://ctan.org/pkg/xkeyval
\newenvironment{realign}[1][]
  {\setkeys{fam}{#1}\myalignment}% \begin{realign}
  {}% \end{realign}

你定义align 选择通过使用键来设置\myalignment(取自xkeyval 文档):

\define@choicekey*{fam}{align}[\val\nr]{left,center,right}{%
  \ifcase\nr\relax
    \def\myalignment{\raggedright}% align=left
  \or
    \def\myalignment{\centering}% align=center
  \or
    \def\myalignment{\raggedleft}% align=right
  \fi
}

但是,现在你有了创建相应布尔值leftcenter并且right等同left|center|right=truealign=left|center|right。是否可以定义布尔值宏定义中的键,例如通过类似如下的方式\newboolkey{left}

\newcommand{\newboolkey}[1]{
  \define@boolkey{fam}[@bool@]{#1}[true]{%
    \csname if@bool@#1\endcsname%
      \setkeys{fam}{align=#1}%
    \fi%
  }%
}

这是行不通的,因为#1的参数\newboolkey没有正确地转换成键的定义left

当然,\define@boolkey从中删除\newboolkey并明确说明键(而不是#1)是可行的。但是,我对以这种方式(手动)创建布尔键不感兴趣。我想使用宏定义来执行此操作,因为它应该是自动化和灵活的。

这是一个不起作用的最小示例:

\documentclass{article}
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\usepackage{xkeyval}% http://ctan.org/pkg/xkeyval
\newenvironment{realign}[1][]
  {\setkeys{fam}{#1}\myalignment}% \begin{realign}
  {}% \end{realign}
\makeatletter
\define@choicekey*{fam}{align}[\val\nr]{left,center,right}{%
  \ifcase\nr\relax
    \def\myalignment{\raggedright}% align=left
  \or
    \def\myalignment{\centering}% align=center
  \or
    \def\myalignment{\raggedleft}% align=right
  \fi
}
\newcommand{\newboolkey}[1]{
  \define@boolkey{fam}[@bool@]{#1}[true]{%
    \csname if@bool@#1\endcsname%
      \setkeys{fam}{align=#1}%
    \fi%
  }%
}

\makeatother
\begin{document}
\begin{realign}[align=left]
\lipsum[1]
\end{realign}

\newboolkey{left}% Create a boolean equivalent for align=left
\makeatletter
\if@bool@left\else% Check if key is defined.
  \texttt{left} key defined
\fi

\begin{realign}[left]% Doesn't work
\lipsum[1]
\end{realign}
\end{document}

答案1

Marco 已经发布了一个版本,但我认为这更接近您想要的版本,只是修复了#1/##1混淆。

\documentclass{article}
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\usepackage{xkeyval}% http://ctan.org/pkg/xkeyval
\newenvironment{realign}[1][]
  {\let\myalignment\relax\setkeys{fam}{#1}\myalignment}% \begin{realign}
  {}% \end{realign}
\makeatletter
\define@choicekey*{fam}{align}[\val\nr]{left,center,right}{%
  \ifcase\nr\relax
    \def\myalignment{\raggedright}% align=left
  \or
    \def\myalignment{\centering}% align=center
  \or
    \def\myalignment{\raggedleft}% align=right
  \fi
}
\newcommand{\newboolkey}[1]{
  \define@boolkey{fam}[@bool@]{#1}[true]{%
    \csname if##1\endcsname
      \setkeys{fam}{align=#1}%
    \csname fi\endcsname
  }%
}

\makeatother
\begin{document}
\begin{realign}[align=left]
\lipsum[1]
\end{realign}

\newboolkey{left}% Create a boolean equivalent for align=left
\makeatletter
\if@bool@left\else% Check if key is defined.
  \texttt{left} key defined
\fi

\begin{realign}[left]% Doesn't work
\lipsum[1]
\end{realign}
\end{document}

答案2

您可以测试的参数define@boolkey。它更容易处理:

\newcommand{\newboolkey}[1]{%
  \define@boolkey{fam}[@bool@]{#1}[true]{%
   \in@{true}{##1}
   \ifin@
     \setkeys{fam}{align=#1}%
  \fi
  }%
}

如果您想使用您的代码,您可以使用:

\newcommand{\newboolkey}[1]{
  \define@boolkey{fam}[@bool@]{#1}[true]{%
    \csname if@bool@#1\endcsname%
      \setkeys{fam}{align=#1}%
    \csname  fi \endcsname%
  }%
}

对我有用的完整代码:

\setcounter{errorcontextlines}{999}
\documentclass{article}
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\usepackage{xkeyval}% http://ctan.org/pkg/xkeyval
\newenvironment{realign}[1][]%
  {\setkeys{fam}{#1}\myalignment}% \begin{realign}
  {}% \end{realign}
\makeatletter
\let\myalignment\relax
\define@choicekey*{fam}{align}[\val\nr]{left,center,right}{%
  \ifcase\nr\relax
    \def\myalignment{\raggedright}% align=left
  \or
    \def\myalignment{\centering}% align=center
  \or
    \def\myalignment{\raggedleft}% align=right
  \fi
}
\newcommand{\newboolkey}[1]{%
  \define@boolkey{fam}[@bool@]{#1}[true]{%
   \in@{true}{##1}
   \ifin@
     \setkeys{fam}{align=#1}%
  \fi
  }%
}

\makeatother
\begin{document}
\begin{realign}[align=center]
\lipsum[1]
\end{realign}

\hrulefill

\newboolkey{left}% Create a boolean equivalent for align=left



\begin{realign}[left]
\lipsum[1]
\end{realign}
\end{document}

答案3

我看到你想定义多个布尔键。我决定使用龙腾包。我本来会使用key environment这个任务,但这是你想要的。我首先想到的也是命令\ltxkeys@declarekeys

\documentclass{article}
\usepackage{lipsum}
\usepackage{ltxkeys}
\makeatletter
\newenvironment{realign}[1][]{%
  \let\myalignment\relax
  \ltxkeys@setkeys[WN]{fam}{#1}\myalignment
}{}
% 1. The *-form of \ltxkeys@choicekey will convert the user input to lowercase 
%    before checking the value against the nominations and executing the callbacks.
% 2. The !-form will fully expand the user input before checking it against
%    the nominations.
% 3. The +-form expects two callbacks (one for when the user input is valid,
%    and the other for when the user input isn't in the nominations).

% \val and \mpcalign hold the same content.
\ltxkeys@choicekey*+![WN]{fam}[mpc]{align}[\val\nr]{%
  center/.code=\let\myalignment\centering,
  left/.code=\let\myalignment\raggedright,
  right/.code=\let\myalignment\raggedleft
}[center]{%
  % Callback for when value is correct, ie, in the list {left,right,center}.
}{%
  \@latexerr{Invalid value for key 'align'}\@ehd
}
% I thought you meant to define more than one boolean key:
\ltxkeys@boolkeys[WN]{fam}[mpb]{left,right,center}[true]{%
  \ifboolFT{mpb\ltxkeys@tkey}{}{%
    \cptexpanded{\ltxkeys@setkeys[WN]{fam}{align=\ltxkeys@tkey}}%
  }%
}
\let\ltxsetkeys\ltxkeys@setkeys
\makeatother
\begin{document}
\begin{realign}[align=left]
\lipsum[1]
\end{realign}
\begin{realign}[align=right]
\lipsum[1]
\end{realign}
\ltxsetkeys[WN]{fam}{right=true}
\ltxsetkeys[WN]{fam}{left=false}
\def\say#1{%
  \cptdocommalist{#1}{%
    \endgraf Key \texttt{##1} set
    \ifboolTF{mpb##1}{true}{false}.
  }%
}
\say{left,right,center}
\end{document}

在此处输入图片描述

相关内容