以保留 catcode 的方式将键值对保存在 `l3prop` 中

以保留 catcode 的方式将键值对保存在 `l3prop` 中

这是这个帖子。最初的问题是将某些函数的选项存储在某个容器中。此类函数的示例:\includepdf、 或\newwatermark。如果选项很多且\function[options]需要重复使用,这种方法会很有用。如果选项直接存储在 中l3seq(第一种方法),则可以正常工作。但我想将选项存储在 中,l3prop因为它可以处理重复项(例如,如果我在扩展点更新选项)。因此,在扩展点需要一个额外的步骤:将选项从 转移到l3propl3seq然后使用 进行扩展\seq_use:Nn。这定义了第二种方法。它适用于\includepdf,但不适用于\newwatermark。但是,有人指出该l3prop方法不保留 catcode,特别是将键的 catcode 更改为l3str。建议的解决方案(下面的代码)带有以下标题:“该代码的第一部分对应于您的编程,结果为 FALSE。在第二种情况下,键在构造上仍然是字符串,结果为 TRUE。”它识别了代码失败的位置,但并未解决问题。因此,主题行中的挑战是:能够将 key-val 对存储在 中l3prop,并且能够恢复提供给它们的 catcode。特别是,它们的扩展适用于\newwatermark[options]

附言:有人建议xwatermark完全放弃。我指出我遇到了问题background

\documentclass{article}
\begin{document}

\ExplSyntaxOn

{
  \seq_set_from_clist:Nn \l_tmpa_seq { key = smth }

  \prop_set_from_keyval:Nn \l_tmpa_prop { key = smth }

  \prop_map_inline:Nn \l_tmpa_prop { \seq_put_right:Nn \l_tmpb_seq { #1 = #2 } }

  \tl_set:Nf \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { } }
  \tl_set:Nf \l_tmpb_tl { \seq_use:Nn \l_tmpb_seq { } }

  \tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl { TRUE } { FALSE } % return FALSE
}

--

{
  \str_set:Nn \l_tmpa_str { key }

  \exp_args:NNx \seq_set_from_clist:Nn \l_tmpa_seq { \l_tmpa_str = smth }

  \exp_args:NNx \prop_set_from_keyval:Nn \l_tmpa_prop { \l_tmpa_str = smth }

  \prop_map_inline:Nn \l_tmpa_prop { \seq_put_right:Nn \l_tmpb_seq { #1 = #2 } }

  \tl_set:Nf \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { } }
  \tl_set:Nf \l_tmpb_tl { \seq_use:Nn \l_tmpb_seq { } }

  \tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl { TRUE } { FALSE } % return TRUE
}


\ExplSyntaxOff

\end{document}

答案1

下面为替代prop结构(基于l3prop的类型)定义了一组函数,该函数将密钥存储两次,一次作为正常prop密钥,一次以未标记化的形式存储在prop的值中。这些函数都名为\erwannprop_...,变量..._eprop。这些函数只是l3propl3seq函数的薄包装。

\documentclass[]{article}

\ExplSyntaxOn
\cs_new_protected:Npn \erwannprop_new:N #1
  { \prop_new:N #1 }
\msg_new:nnn { erwannprop } { no-value }
  { Missing~ '='~ in~ '#1'~ (in~ ..._keyval:Nn) }
\cs_new_protected:Npn \erwannprop_set_from_keyval:Nn #1#2
  {
    \prop_clear:N #1
    \keyval_parse:nnn
      { \msg_error:nnn { erwannprop } { no-value } }
      { \erwannprop_put:Nnn #1 }
      {#2}
  }
\cs_new_protected:Npn \erwannprop_put:Nnn #1#2#3
  { \prop_put:Nnn #1 {#2} { {#2} {#3} } }
\cs_new_protected:Npn \erwannprop_to_seq:NN #1#2
  {
    \seq_clear:N #2
    \prop_map_tokens:Nn #1 { \__erwannprop_to_seq:Nnn #2 }
  }
\cs_new_protected:Npn \__erwannprop_to_seq:Nnn #1#2#3
  { \__erwannprop_to_seq_aux:Nnn #1 #3 }
\cs_new_protected:Npn \__erwannprop_to_seq_aux:Nnn #1#2#3
  { \seq_put_right:Nn #1 { #2 = #3 } }
\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn
\erwannprop_new:N \l_tmpa_eprop
\seq_set_from_clist:Nn \l_tmpa_seq { key = smth }
\erwannprop_set_from_keyval:Nn \l_tmpa_eprop { key = smth }
\erwannprop_to_seq:NN \l_tmpa_eprop \l_tmpb_seq

\tl_set:Nf \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { } }
\tl_set:Nf \l_tmpb_tl { \seq_use:Nn \l_tmpb_seq { } }

\tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl { TRUE } { FALSE }
\ExplSyntaxOff

\end{document}

答案2

可以使用 来重新\tl_set_rescan:Nnn标记expl3

但是,我们根本不推荐这样做。正如文档中所说(interface3.pdf):

虽然支持此功能,但通常最好找到实现结果的替代方法,而不是重新扫描令牌。

我写这个答案只是为了提供一般信息。

\documentclass{article}
\begin{document}

\ExplSyntaxOn

{
  \seq_set_from_clist:Nn \l_tmpa_seq { key = smth }

  \prop_set_from_keyval:Nn \l_tmpa_prop { key = smth }

  \prop_map_inline:Nn \l_tmpa_prop { \seq_put_right:Nn \l_tmpb_seq { #1 = #2 } }

  \tl_set:Nf \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { } }
  \tl_set:Nf \l_tmpb_tl { \seq_use:Nn \l_tmpb_seq { } }

  \tl_set_rescan:Nno \l_tmpb_tl { } \l_tmpb_tl
  \tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl { TRUE } { FALSE } % return TRUE because of the previous line
}

--

{
  \str_set:Nn \l_tmpa_str { key }

  \exp_args:NNx \seq_set_from_clist:Nn \l_tmpa_seq { \l_tmpa_str = smth }

  \exp_args:NNx \prop_set_from_keyval:Nn \l_tmpa_prop { \l_tmpa_str = smth }

  \prop_map_inline:Nn \l_tmpa_prop { \seq_put_right:Nn \l_tmpb_seq { #1 = #2 } }

  \tl_set:Nf \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { } }
  \tl_set:Nf \l_tmpb_tl { \seq_use:Nn \l_tmpb_seq { } }

  \tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl { TRUE } { FALSE } % return TRUE
}


\ExplSyntaxOff

\end{document}

相关内容