有没有办法向命令添加可选和/或命名参数

有没有办法向命令添加可选和/或命名参数

我正在为我的学生编写一本手册,我想创建一个命令,该命令应该绘制任务定义、其类型和可能的特征,例如来源和指向 YouTube 上的解决方案的链接。

在我的计划中,所有这些定义都应该起作用(当然,我在这里故意使用伪语法,只是为了向你展示我的意图):

  • \task{definition=$x=3$}
  • \task{definition=$x=3$, source='ABC'}
  • \task{definition=$x=3$, link='https://youtube.ru'}
  • \task{definition=$x=3$, source='ABC', link='https://youtube.ru'}

但我找不到任何类似于可选和命名参数的工具。

答案1

传统的 LaTeX2e 解决方案是keyval包(由 所使用\includegraphics[height=2cm, scale=3]{...}),但最近的 LaTeX 版本包含一个基于 的内置 keyval 解析器l3keys

@Campa 的示例经过修改以使用较新的系统:

\documentclass{article}


\makeatletter
\DeclareKeys[task]{
definition .store = \task@definition,
source     .store = \task@source,
link       .store = \task@link
}



\NewDocumentCommand\task{m}{%
   \begingroup
   \SetKeys[task]{#1}%
   This is a task with definition \task@definition.%
   \ifx\task@source\@empty\else\space You can find its source in \task@source.\fi
   \ifx\task@link\@empty\else\space (See \task@link)\fi
   \endgroup
}
\makeatother

\begin{document}
\parindent0pt
\task{definition={$x=3$}}\par % you must "hide" the =
\task{definition={$x=3$}, source=ABC}\par
\task{definition={$x=3$}, link=https://youtube.ru}\par
\task{definition={$x=3$}, source=ABC, link=https://youtube.ru}
\task{definition={$x=3$}} % you must "hide" the =
\end{document}

答案2

这可能是开始使用keyval

\documentclass{article}

\usepackage{keyval}
\makeatletter
\newcommand*{\task@definition}{}
\newcommand*{\task@source}{}
\newcommand*{\task@link}{}
\define@key{task}{definition}{\def\task@definition{#1}}
\define@key{task}{source}{\def\task@source{#1}}
\define@key{task}{link}{\def\task@link{#1}}
\newcommand*{\task}[1]{%
   \begingroup
   \setkeys{task}{#1}%
   This is a task with definition \task@definition.%
   \ifx\task@source\@empty\else\space You can find its source in \task@source.\fi
   \ifx\task@link\@empty\else\space (See \task@link)\fi
   \endgroup
}
\makeatother

\begin{document}
\parindent0pt
\task{definition={$x=3$}}\par % you must "hide" the =
\task{definition={$x=3$}, source=ABC}\par
\task{definition={$x=3$}, link=https://youtube.ru}\par
\task{definition={$x=3$}, source=ABC, link=https://youtube.ru}
\task{definition={$x=3$}} % you must "hide" the =
\end{document}

在此处输入图片描述

答案3

对于一个简单的任务,在我看来1expkv-cs ,没有什么比和的简单性更好\ekvcSplit(这只适用于最多 9 个键,对于更多键,最好使用expkv-def类似于\DeclareKeys-- 的方法或另一个 key=value 实现,如 LaTeX 内置的实现)。

1我是《和家人》的作者expkv

为了能够轻松地向键添加格式说明和额外文本,可以使用装饰某些内部键的正面键。因此每次您说link = www.example.com这句话时都会变成link-internal={ (See www.example.com)}

另外,expkv您不必隐藏额外的=,但您必须隐藏一个,

这借用了@campa 创建的示例并对其进行了修改以使用expkv-cs

\documentclass{article}

\usepackage{expkv-cs}

\ekvcSplit\task
  {
    % set up primary keys, all defaulting to an empty value
     definition = {}
    ,source-internal = {}
    ,link-internal = {}
  }
  {This is a task with definition #1.#2#3}
% set up decorators
\ekvcSecondaryKeys\task
  {
     meta source = {source-internal = { You can find its source in #1.}}
    ,meta link   = {link-internal   = { (See #1)}}
  }

\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}

除了版本之外\ekvcSplit,您还可以使用版本\ekvcHash,其中您可以通过名称访问键值(整个列表将在内部转发#1\ekvcValue并可用于访问该列表中的项目 - 这适用于任意多个键)。

\documentclass{article}

\usepackage{expkv-cs}

\ekvcHash\task
  {
    % set up primary keys, all defaulting to an empty value
     definition = {}
    ,source-internal = {}
    ,link-internal = {}
  }
  {%
    This is a task with definition \ekvcValue{definition}{#1}.%
    \ekvcValue{source-internal}{#1}%
    \ekvcValue{link-internal}{#1}%
  }
% set up decorators
\ekvcSecondaryKeys\task
  {
     meta source = {source-internal = { You can find its source in #1.}}
    ,meta link   = {link-internal   = { (See #1)}}
  }

\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}

如果您想要一个更接近于 提供的接口,\DeclareKeys您可以使用expkv-def。除了store-handler 之外,它还提供dataT。指令dataT link = \taskLink将定义\taskLink这样一种方式,即默认情况下它将吞噬下一个标记或大括号组,但如果使用了键,它将把值放在{<value>}下一个标记或大括号组的后面(并从后面的大括号组中剥离大括号)。

\documentclass{article}

\usepackage{expkv-def}

\ekvdefinekeys{task}
  {
     store definition = \taskDefinition
    ,dataT source     = \taskSource
    ,dataT link       = \taskLink
  }
\newcommand\taskSourceFormatter[1]{ You can find its source in #1.}
\newcommand\taskLinkFormatter[1]{ (See #1)}

\newcommand\task[1]
  {%
    \begingroup
      \ekvset{task}{#1}%
      This is a task with definition \taskDefinition.%
      \taskSource\taskSourceFormatter
      \taskLink\taskLinkFormatter
    \endgroup
  }

\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}

如果您确实想要,那么您可以使用与keyval使用基本包基本相同的语法,expkv而无需任何扩展包:

\documentclass{article}

\usepackage{expkv}

\newcommand*\taskDefinition{}
\newcommand*\taskSource{}
\newcommand*\taskLink{}
\ekvdef{task}{definition}{\def\taskDefinition{#1}}
\ekvdef{task}{source}{\def\taskSource{#1}}
\ekvdef{task}{link}{\def\taskLink{#1}}

\newcommand\task[1]
  {%
    \begingroup
      \ekvset{task}{#1}%
      This is a task with definition \taskDefinition.%
      \ifx\taskSource\empty\else\space You can find its source in \taskSource.\fi
      \ifx\taskLink\empty\else\space (See \taskLink)\fi
    \endgroup
  }

\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}

所有代码块的结果:

在此处输入图片描述

相关内容