¿Cómo puedo guardar opciones clave-valor que incluyen opciones clave-valor en expl3?

¿Cómo puedo guardar opciones clave-valor que incluyen opciones clave-valor en expl3?

Tengo un comando que utiliza una sintaxis clave-valor. Por ejemplo, incluye una imagen con varias opciones, si se desea.

Estoy usando el procesamiento de valores clave expl3.

Me gustaría guardar la configuración clave-valor en una lista global de tokens, para poder reutilizarlas como valores predeterminados la próxima vez que se ejecute el comando. No pude encontrar una manera obvia de hacer esto, ya que no quiero que las macros con las opciones clave-valor configuradas sean globales, ya que hacerlo global complicaría las cosas de varias maneras. Todo lo que quiero es guardar los valores-clave relevantes en una lista de tokens global para poder reutilizarlos. (No me importa si no es una lista simbólica; esa parecía la opción obvia).

Parece que puedo guardar bien los valores booleanos y las listas separadas por comas, pero tengo problemas con las listas de tokens que son a su vez listas de opciones clave-valor. Por ejemplo, graphics={<key-value options>}se utiliza para pasar configuraciones a \includegraphics. Sin embargo, no puedo hacer que esto funcione.

Aquí hay un ejemplo (comparativamente) mínimo, lo que hace que no sea completamente obvio por qué estoy tratando de hacer esto en Venus, pero eso es miniaturización para usted.

\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}

El mensaje de error me sugiere que le pida ayuda a un humano, así que aquí estoy...

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! 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.''                                                                                                 

?   

Si muestro la lista de tokens antes de intentar usarla, obtengo

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

lo que sugiere a mi mente simple que de alguna manera necesito incluir llaves alrededor de la lista. Sin embargo, mis intentos de lograrlo hasta ahora no han tenido éxito. O LaTeX busca algo que no debe ser una clave (por ejemplo \g_pre_img_options, ) o los corchetes simplemente se evaporan.

Respuesta1

No entiendo del todo lo que estás tratando de lograr, y sea lo que sea que supongo, no creo que lo haría de la misma manera, pero, en cualquier caso, aquí hay un cambio que hace que ese documento se compile.

\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 { , }
    }
}

Esto parece incorrecto, incluso si no lo entiendo claramente, eso es, por un lado, complicar demasiado el problema con muchas partes diferentes, y también, el hecho de que en realidad no se puede hacer eso (agregar \c_left_brace_strno es agregar un código de gato de grupo de apertura 1 {sino un catcode “otro”, similar a \string{). Es más sencillo con un xargumento sencillo, con el \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 } } , }
   }
 }

Con este cambio al menos se compila, pero no sé si con esto se soluciona todo.


Quiere agregar una cadena y el valor de una macro a otra macro. La forma más sencilla de hacerlo es hacerlo todo a la vez con un xargumento. Es literalmente hacer lo que querías hacer, pero correcto. \tl_put_right:Nxexpande el segundo argumento en un \edef, es decir, expandetodo, por lo que sólo deberás parar en el momento preciso que desees. Después de sustituir los argumentos terminas con

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

Si vieras \edef\foo{graphics={foo}}entenderías cuál \foosería el contenido de: nada se expande, ni las letras, ni los “otros” (“="”), ni las llaves {y }. Entonces la magia está dentro \exp_not:v { l_pre_grahpics_tl }. Gracias a los argumentos de expl3, eso es exactamente lo mismo que, \exp_not:V \l_pre_grahpics_tla su vez, es lo mismo \exp_not:n { width=\textwidth }que simplemente detiene la expansión allí ( \exp_not:nis \unexpanded).

De esa manera, la línea de arriba, después de la xexpansión, termina siendo exactamente

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

si no fuera por \unexpanded{width=\textwidth}TeX podría haber intentado expandirse \textwidthcomo con cualquier otra macro, que (no estoy seguro en este momento) podría haberse expandido \dimen <number>y, en general, no queremos que esa expansión suceda.

Lo sentimos, pero cualquiera es libre de editar esta respuesta, que es todo menos perfecta.

información relacionada