Como posso salvar opções de valores-chave que incluem opções de valores-chave em expl3?

Como posso salvar opções de valores-chave que incluem opções de valores-chave em expl3?

Eu tenho um comando que usa uma sintaxe de valor-chave. Por exemplo, inclui uma imagem com várias opções, se desejar.

Estou usando o processamento de valor-chave expl3.

Gostaria de salvar as configurações de valor-chave em uma lista global de tokens, para que possa reutilizá-las como padrão na próxima vez que o comando for executado. Não consegui encontrar uma maneira óbvia de fazer isso, pois não quero tornar as macros as opções de valor-chave definidas como globais, pois torná-las globais complicaria as coisas de várias maneiras. Tudo o que quero é salvar os valores-chave relevantes em uma lista global de tokens para poder reutilizá-los. (Não me importo se não é uma lista de tokens - essa parecia a escolha óbvia.)

Parece que consigo salvar booleanos e listas separadas por vírgula, mas estou tendo problemas com listas de tokens, que são listas de opções de valores-chave. Por exemplo, graphics={<key-value options>}é usado para passar configurações para arquivos \includegraphics. No entanto, não consigo fazer isso funcionar.

Aqui está um exemplo (comparativamente) mínimo, que torna completamente óbvio por que estou tentando fazer isso em Vênus, mas isso é miniaturização para você.

\documentclass{article}
\usepackage{xparse,graphicx}
\begin{document}
\ExplSyntaxOn
\tl_new:N \l_pre_graphics_tl
\tl_new:N \g_pre_img_options_tl
\tl_new:N \g_pre_img_tl
\cs_new_protected_nopar:Nn \pre_key_tl_save:Nn
{
  \tl_if_empty:cF {l_pre_#2_tl}
    {
      \tl_gput_right:No #1 { #2 = }
      \tl_gput_right:NV #1 \c_left_brace_str
      \tl_gput_right:Nv #1 { l_pre_#2_tl }
      \tl_gput_right:NV #1 \c_right_brace_str
      \tl_gput_right:Nn #1 { , }
    }
}
\cs_generate_variant:Nn \tl_gput_right:Nn {Nv}
% includegraphics bit courtesy of egreg (chat 2015-01-08)
\cs_new:Npn \pre_includegraphics:nn #1 #2
 {
  \includegraphics[#1]{#2}
 }
\cs_generate_variant:Nn \pre_includegraphics:nn { VV }
\keys_define:nn { pre / img }
{
  graphics .tl_set:N = \l_pre_graphics_tl,
}
\NewDocumentCommand \incimg { o m }
{
  \group_begin:
    \tl_if_empty:NF \g_pre_img_options_tl
    {
      \keys_set:nV { pre / img } \g_pre_img_options_tl
    }
    \IfValueT{#1}{ \keys_set:nn { pre / img } { #1 } }
    \pre_key_tl_save:Nn \g_pre_img_options_tl { graphics }
    \tl_set:Nn \g_pre_img_tl { #2 }
    \pre_includegraphics:VV \l_pre_graphics_tl \g_pre_img_tl
  \group_end:
}
\ExplSyntaxOff

\incimg[
  graphics={width=\textwidth},
]{example-image-a}
\incimg[
  graphics={width=\textwidth},
]{example-image-a}
\end{document}

A mensagem de erro sugeriu que eu pedisse ajuda a um humano, então aqui estou....

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! LaTeX error: "kernel/misplaced-equals-sign"
! 
! Misplaced equals sign in key-value input 194
! 
! See the LaTeX3 documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

l.194 ]{example-image-a}

? h
|'''''''''''''''''''''''''''''''''''''''''''''''                                                                                              
| LaTeX is attempting to parse some key-value input but found two equals signs                                                                
| not separated by a comma.                                                                                                                   
|...............................................                                                                                              
? h                                                                                                                                           
Sorry, I already gave what help I could...                                                                                                    
Maybe you should try asking a human?                                                                                                          
An error might have occurred before I noticed any problems.                                                                                   
``If all else fails, read the instructions.''                                                                                                 

?   

Se eu mostrar a lista de tokens antes de tentar usá-la, recebo

> \g_pre_img_options_tl=graphics={width=\textwidth },.

o que sugere, para minha mente simplória, que preciso incluir colchetes na lista de alguma forma. No entanto, minhas tentativas de fazer isso até agora não tiveram sucesso. Ou o LaTeX procura por algo que não pretende ser uma chave (por exemplo, \g_pre_img_options) ou os colchetes simplesmente evaporam.

Responder1

Não entendo inteiramente o que você está tentando alcançar e, seja lá o que estou supondo, não acho que faria da mesma maneira, mas, de qualquer forma, aqui está uma alteração que faz com que esse documento seja compilado.

\cs_new_protected_nopar:Nn \pre_key_tl_save:Nn
{
  \tl_if_empty:cF {l_cfr_#2_tl}
    {
      \tl_gput_right:No #1 { #2 = }
      \tl_gput_right:NV #1 \c_left_brace_str
      \tl_gput_right:Nv #1 { l_pre_#2_tl }
      \tl_gput_right:NV #1 \c_right_brace_str
      \tl_gput_right:Nn #1 { , }
    }
}

Isso parece errado, mesmo que eu não entenda isso claramente, isso é, por um lado, complicar demais o problema com muitas partes diferentes, e também, o fato de que você não pode realmente fazer isso (adicionar \c_left_brace_strnão é adicionar um código de grupo de abertura 1, {mas um catcode “outro”, semelhante a \string{). É mais simples com um xargumento simples, com o correto \exp_not:*.

\cs_new_protected_nopar:Nn \pre_key_tl_save:Nn
 {
  \tl_if_empty:cF {l_cfr_#2_tl}
   {
    \tl_gput_right:Nx #1 { #2 = { \exp_not:v { l_pre_#2_tl } } , }
   }
 }

Com essa mudança pelo menos compila, mas não sei se isso resolve tudo.


Você deseja adicionar uma string e o valor de uma macro a outra macro. A maneira mais fácil de fazer isso é discutir tudo de uma vez x. É literalmente fazer o que você queria fazer, mas correto. \tl_put_right:Nxexpande o segundo argumento em an \edef, ou seja, expandetudo, então você só precisa parar no momento exato que desejar. Depois de substituir argumentos você termina com

\tl_gput_right:Nx \g_pre_img_options_tl { graphics = { \exp_not:v { l_pre_grahpics_tl } } , }

Se você viu \edef\foo{graphics={foo}}entendeu qual \fooseria o conteúdo de: nada expande, nem as letras, nem os “outros” (“=”), nem os colchetes {e }. Então a magia está dentro \exp_not:v { l_pre_grahpics_tl }. Graças aos argumentos expl3, isso é exatamente o mesmo que, \exp_not:V \l_pre_grahpics_tlpor sua vez, é o mesmo \exp_not:n { width=\textwidth }que apenas interrompe a expansão ( \exp_not:nis \unexpanded).

Dessa forma, a linha acima, após a xexpansão, acaba ficando exatamente

\tl_gput_right:Nn \g_pre_img_options_tl { graphics = { width = \textwidth } , }

se não fosse pelo \unexpanded{width=\textwidth}TeX poderia ter tentado expandir \textwidthcomo acontece com qualquer outra macro, que (não tenho certeza agora) poderia ter sido expandida \dimen <number>e, em geral, não queremos que essa expansão aconteça.

Desculpe, mas qualquer pessoa é livre para editar esta resposta, que é tudo menos perfeita.

informação relacionada