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_str
não é adicionar um código de grupo de abertura 1, {
mas um catcode “outro”, semelhante a \string{
). É mais simples com um x
argumento 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:Nx
expande 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 \foo
seria 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_tl
por sua vez, é o mesmo \exp_not:n { width=\textwidth }
que apenas interrompe a expansão ( \exp_not:n
is \unexpanded
).
Dessa forma, a linha acima, após a x
expansã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 \textwidth
como 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.