内联 key-val 解析器的正确用法是什么?

内联 key-val 解析器的正确用法是什么?

我假设\keyval_parse:nnn吸收了它的第三个参数,但它却插入到了输入流中,为什么?

\documentclass{report}
\usepackage{xparse}

\begin{document}

\ExplSyntaxOn
\noindent%
\keyval_parse:nnn{}{}{j=u}\\
\keyval_parse:nnn{\use_none:n{##1}}{\use_none:nn{##1}{##2}}{k=v}\\
\keyval_parse:NNn\use_none:n\use_none:nn{l=w}
\ExplSyntaxOff

\end{document}

在此处输入图片描述 在此处输入图片描述

答案1

您需要仔细查看文档中的示例,以了解其作用。假设一个简单的示例,\keyval_parse:nn要求每个键都有一个值,只是为了简化。输入:

\keyval_parse:nn { <keyval code> } { key 1 = value 1, key 2 = value 2 }

相当于:

<keyval code>{key 1}{value 1}
<keyval code>{key 2}{value 2}

也就是说,对于每个,key=value它都会在括号中插入和<keyval code>。对于仅限键的版本也是如此,但它只会在代码后插入一个括号组:keyvalue

<keyval code>{key 1}
<keyval code>{key 2}

前两个示例仅打印了键值列表,因为它们实际上并未使用键值对。仔细观察,规则与之前相同:

\keyval_parse:nnn{}{}{j=u}

这里<keyval code>是空的,因此变成:

%↓ empty
  {j}{u}

它仅写入ju输出。

第二个例子是:

\keyval_parse:nnn{\use_none:n{##1}}{\use_none:nn{##1}{##2}}{k=v}

变成:

\use_none:nn{##1}{##2}{k}{v}

然后\use_none:nn消耗##1##2再次kv排版。


这是一个可能更有启发性的例子。看看\erwann_wrap_one:n他们的论点是什么,并与 PDF 输出进行比较:

\documentclass{article}
\usepackage{xparse}
\begin{document}

\ExplSyntaxOn
\noindent
\cs_new:Npn \erwann_wrap_one:n #1 { (#1) }
\cs_new:Npn \erwann_wrap_two:nn #1 #2 { [#1--#2] }
\keyval_parse:nnn
  { \typeout{A~KEY} \erwann_wrap_one:n }
  { \typeout{A~KEY~WITH~VALUE} \erwann_wrap_two:nn }
  {
    k1,
    k2 = v,
  }
\ExplSyntaxOff

\end{document}

这将打印

A KEY
A KEY WITH VALUE

到终端,PDF 将具有:

在此处输入图片描述

答案2

第一个参数应该\keyval_parse:nnn以需要括号参数的内容结尾。

类似地,第二个参数应该以需要两个括号参数的内容结尾。

在您的第一次通话中,您只会得到{j}{u}

这些示例使用了一个双参数函数和一个三参数函数,但只提供了一个参数,其他参数将通过解析提供。

当然这不是为了打印什么东西,而是做一些设置。

打印示例:

\documentclass{article}

\ExplSyntaxOn

\cs_new:Nn \erwann_test:n { \#1~is~#1 }
\cs_new:Nn \erwann_test:nn { \#1~is~#1;~ \#2~is~#2 }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\keyval_parse:nnn { \erwann_test:n } { \erwann_test:nn } { j=u , k }

\ExplSyntaxOff

\end{document}

在此处输入图片描述

带有设置的示例。

\documentclass{article}

\ExplSyntaxOn

\seq_new:N \l_erwann_test_seq
\prop_new:N \l_erwann_test_prop

\cs_new_protected:Nn \erwann_set:n
 {
  \keyval_parse:nnn
   {
    \seq_put_right:Nn \l_erwann_test_seq
   }
   {
    \prop_put:Nnn \l_erwann_test_prop
   }
   { #1 }
 }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\erwann_set:n { j, k=a, yy=b, c }

\seq_show:N \l_erwann_test_seq
\prop_show:N \l_erwann_test_prop

\ExplSyntaxOff

\end{document}

终端上的结果

The sequence \l_erwann_test_seq contains the items (without outer braces):
>  {j}
>  {c}.
<recently read> }

l.28 \seq_show:N \l_erwann_test_seq

?
The property list \l_erwann_test_prop contains the pairs (without outer
braces):
>  {k}  =>  {a}
>  {yy}  =>  {b}.
<recently read> }

l.29 \prop_show:N \l_erwann_test_prop

?

\keyval_parse:NNn函数的作用基本相同,但你只需传递一个单参数函数和一个双参数函数。因此,上面的代码也可以写成

\documentclass{article}

\ExplSyntaxOn

\seq_new:N \l_erwann_test_seq
\prop_new:N \l_erwann_test_prop

\cs_new_protected:Nn \erwann_set:n
 {
  \keyval_parse:nnn \erwann_set_one:n \erwann_set_two:nn { #1 }
 }
\cs_new_protected:Nn \erwann_set_one:n
 {
  \seq_put_right:Nn \l_erwann_test_seq { #1 }
 }
\cs_new_protected:Nn \erwann_set_two:nn
 {
  \prop_put:Nnn \l_erwann_test_prop { #1 } { #2 }
 }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\erwann_set:n { j, k=a, yy=b, c }

\seq_show:N \l_erwann_test_seq
\prop_show:N \l_erwann_test_prop

\ExplSyntaxOff

\end{document}

相关内容