简单键值示例

简单键值示例

我尝试使用如下命令来制作 pgfkeys(或其他 keystyle 参数包)的一个非常简单的示例:

\mycommand{title="The new book", author="John Doe"}

得到这样的行为:

作家约翰·多伊

标题 新书

并且,如果缺少某个键,则该行可能不会出现。例如,命令

\mycommand{title="The new book"}

仅会打印:

标题 新书

我检查了网络和 StackExchange,但我只发现了非常复杂的例子,其中包括很多与键值语法不直接相关的其他内容。

那么,我怎样才能输入这样最小的键值命令呢?

答案1

我不确定你真正需要什么。这可以作为开始...

分配给titleauthor实际上运行在中定义的代码pgfkeys。不存储任何内容。

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{
    /bibliography/.cd, % family
    title/.code = {\ifx#1\empty A\else{\textbf{Title} #1\par}\fi},
    author/.code = {\ifx#1\empty A\else{\textbf{Author} #1\par}\fi},
}

\newcommand{\mycommand}[1]{
    \pgfkeys{
        /bibliography/.cd,
        #1,
    }
    \pgfkeysvalueof{/bibliography/title}
    \pgfkeysvalueof{/bibliography/author}
}
\begin{document}
One:\par
\mycommand{title = {Tikz \& PGF}, author={JD}}

Two:\par
\mycommand{author={JD}}

Three:\par
\mycommand{title = {Tikz \& PGF}}

Four:\par
\mycommand{}

Five:\par
\mycommand{title=, author=}

\end{document}

编辑

请注意,是.code在“参数时间”执行的,因此\mycommand{author={JD}, title = {Tikz \& PGF}}会在标题之前打印作者。

编辑2

此版本使用\bibtitle\bibauthor来存储数据。由于这些宏是全局的,因此您必须在每次调用时清除它们(设置为空),否则会记住以前的值。

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{
    /bibliography/.cd, % family
    title/.store in = \bibtitle,
    author/.store in = \bibauthor,
}

\newcommand{\mycommand}[1]{
    \pgfkeys{
        /bibliography/.cd,
        title = {},  % clear title
        author = {}, % clear author
        #1,
    }
    \ifx\bibtitle\empty\else\textbf{Title:} \bibtitle\par\fi
    \ifx\bibauthor\empty\else\textbf{Author:} \bibauthor\par\fi
}
\begin{document}
One:\par
\mycommand{title = {Tikz \& PGF}, author={JD}}
\mycommand{author={JD}, title = {Tikz \& PGF}}
    
\vspace{2ex}
Two:\par
\mycommand{author={JD}}

\vspace{2ex}
Three:\par
\mycommand{title = {Tikz \& PGF}}

\vspace{2ex}
Four:\par
\mycommand{}

\vspace{2ex}
Five:\par
\mycommand{title=, author=}

\end{document}

答案2

这是一个带有键的实现expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

% define the keys
\keys_define:nn { fauve/books }
 {
  title  .tl_set:N = \l__fauve_books_title_tl, % the title
  author .tl_set:N = \l__fauve_books_author_tl, % the author
 }

% formatting
\NewDocumentCommand{\mycommand}{m}
 {
  \group_begin:
  \keys_set:nn { fauve/books } { #1 } % populate the keys

  % format the book
  \par\addvspace{\topsep}
  \fauve_books_author:V \l__fauve_books_author_tl
  \fauve_books_title:V \l__fauve_books_title_tl
  \par\addvspace{\topsep}
  \group_end:
 }

\cs_new_protected:Nn \fauve_books_title:n
 {
  \tl_if_empty:nF { #1 }
   {
    \par\noindent\textbf{Title:}~#1
   }
 }
\cs_new_protected:Nn \fauve_books_author:n
 {
  \tl_if_empty:nF { #1 }
   {
    \par\noindent\textbf{Writer:}~#1
   }
 }
\cs_generate_variant:Nn \fauve_books_title:n  {V}
\cs_generate_variant:Nn \fauve_books_author:n {V}

\ExplSyntaxOff

\begin{document}

\mycommand{title=The new book, author=John Doe}

\mycommand{title=Another book}

\end{document}

我已经分离了每个键特定的格式化命令,但这是可选的。

在此处输入图片描述

答案3

无论如何,我将展示如何在 ConTeXt 中编写这样的宏。ConTeXt 有几个键值驱动接口,但对于像这样简单的东西,我只需借助\setupvariables[...][..=..]\getvariable{...}{...}

\unprotect
\define\mycommand
    {\dosingleargument\mycommand_setup}

\def\mycommand_setup[#1]%
    {\bgroup
     \setvariables[mycommand][#1]%
     \mycommand_process
     \egroup}

\def\mycommand_process
    {\startlines
     \doifsomething{\getvariable{mycommand}{author}}
        {\bold{Writer:} \getvariable{mycommand}{author}\endgraf}%
     \doifsomething{\getvariable{mycommand}{title}}
        {\bold{Title:} \getvariable{mycommand}{title}}%
     \stoplines}
\protect

\starttext
\mycommand[title={The new book}, author={John Doe}]

\mycommand[title={The new book}]
\stoptext

请注意,我修改了界面(使用\mycommand[...]而不是\mycommand{...})以符合 ConTeXt 约定,即方括号中的参数用于选项,大括号中的参数用于排版的文本。

答案4

使用expkv-cs最少的 key=value 宏非常容易实现。

在这种情况下,我们可能还希望在给定或不给​​定键的情况下有不同的行为。这可以通过一个间接级别相对容易地实现,其中第一级包含默认值(如果未提供任何内容),第二级添加标记/格式化指令(如果使用了键)。这样,我们不需要在宏替换中进行任何测试,但可以直接使用这些值(即使它们是空的)。为此,以下使用-internal真正的键,但添加包装器来添加类似\par\noindent或类似的东西。

\documentclass[]{article}

\usepackage{expkv-cs}
% declaring the internal keys and the order of output.
\ekvcSplit\mycommand
  {
    % long since it'll get a `\par` token by the frontend key
     long author-internal = {}              % #1
    ,     title-internal  = \emph{No title} % #2
    ,long year-internal   = {}              % #3
  }
  {#1\par\noindent#2#3}

% Declaring the front level keys and how they interact with the internal keys.
% A meta key will set other keys, so if `year=YYYY` is called it'll be
% equivalent to `year-internal=\par\noindent\textbf{Year} YYYY`
\ekvcSecondaryKeys\mycommand
  {
    % for a single key=value pair set by a `meta` secondary key we don't need
    % additional braces guarding the second = in expkv. The following is
    % equivalent to
    % meta author = {author-internal = {\par\noindent\textbf{Writer} #1}}
     meta author = author-internal = {\par\noindent\textbf{Writer} #1}
    ,meta title  = title-internal  = {\textbf{Title} #1}
    ,meta year   = year-internal   = {\par\noindent\textbf{Year} #1}
  }

\begin{document}
\mycommand{title=The new book,author=John Doe}
\bigskip
\mycommand{title=The new book}
\bigskip
\mycommand{title=The new book,year=2020}
\bigskip
\mycommand{author=John Doe,year=2020}
\end{document}

在此处输入图片描述

相关内容