Как преобразовать clist в keyval prop?

Как преобразовать clist в keyval prop?

Я пытаюсь сохранить список, разделенный запятыми, в свойстве «ключ-значение», чтобы использовать его позже, но мне не удаётся заставить его работать правильно.

Я не совсем понимаю, как latex анализирует параметр keyval, но предполагаю, что он обрабатывает параметр как обычный текст.

Вот код, который у меня сейчас есть:

\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand { \getvmeta } { m } { \prop_item:cn { g_rvnlatex_doc_prop } { #1 } }
\NewDocumentCommand { \setvmeta } { m m } { \prop_gput:cnV { g_rvnlatex_doc_prop } { #1 } #2 }

\keys_define:nn { ravenhill/latex/meta } {
    author .clist_set:N = \l_rvnlatex_author_clist ,
}

\NewDocumentCommand { \setup } { m } { 
  \group_begin:
  \prop_new:c { g_rvnlatex_doc_prop }
  \keys_set:nn { ravenhill/latex/meta } { #1 }
  \setvmeta { author } { \l_rvnlatex_author_clist }
  \group_end:
}

\NewDocumentCommand { \authorblock } { } {
  \clist_new:N \l__authblock_authcopy_clist
  \clist_set:Nn \l__authblock_authcopy_clist { \getvmeta { author } }
  \clist_use:Nnnn \l__authblock_authcopy_clist { ~and~ } { ,~ } { ,~and~ }
}
\ExplSyntaxOff
  
\setup { 
    author = {John, Bob},
}

\begin{document}
  \authorblock
\end{document}

Результат, который я получил, — John,Bobвместо John and Bob.

Я что-то упускаю?

решение1

Ваша догадка верна. Когда вы используете

\clist_set:Nn \l__authblock_authcopy_clist { \getvmeta { author } }

анализатор clist видит только \getvmeta { author }то, что, насколько это касается его, ничем не отличается отgetvmeta { author } , поскольку в нем нет запятой.

Чтобы раскрыть переданный вами ключу список запятых author, вам нужно расширить \getvmeta{author}его содержимое. Для этого используйте \clist_set:Nx( xозначает исчерпывающее расширение). Это сработает, потому что \prop_item:Nnработает путем расширения, поэтому может вернуть элемент в контексте расширения (вы также должны разрешить \getvmetaрасширение, объявив его с помощью ).\NewExpandableDocumentCommand

Кроме того, вынесите объявления переменных за пределы команд уровня пользователя: никогда не знаешь, попытается ли кто-то использовать их, скажем, \setupдважды, и если он это сделает, ваш код выдаст ошибку при попытке объявить переменную, которая уже существует.

\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\NewExpandableDocumentCommand { \getvmeta } { m }
  { \prop_item:Nn \g_rvnlatex_doc_prop {#1} }
\NewDocumentCommand { \setvmeta } { m m }
  { \prop_gput:NnV \g_rvnlatex_doc_prop {#1} #2 }

\keys_define:nn { ravenhill/latex/meta }
  { author .clist_set:N = \l_rvnlatex_author_clist }

\prop_new:N \g_rvnlatex_doc_prop
\clist_new:N \l__authblock_authcopy_clist

\NewDocumentCommand \setup { m }
  {
    \group_begin:
      \keys_set:nn { ravenhill/latex/meta } {#1}
      \setvmeta { author } { \l_rvnlatex_author_clist }
    \group_end:
  }

\NewDocumentCommand \authorblock { }
  {
    \clist_set:Nx \l__authblock_authcopy_clist { \getvmeta { author } }
    \clist_use:Nnnn \l__authblock_authcopy_clist { ~and~ } { ,~ } { ,~and~ }
  }
\ExplSyntaxOff

\setup{author = {John, Bob}}

\begin{document}
  \authorblock
\end{document}

Связанный контент