如何儲存包含 expl3 中鍵值選項的鍵值選項?

如何儲存包含 expl3 中鍵值選項的鍵值選項?

我有一個使用鍵值語法的命令。例如,如果需要,它包括帶有各種選項的圖像。

我正在使用 expl3 鍵值處理。

我想將鍵值設定儲存到全域令牌清單中,以便下次執行命令時可以將它們重新用作預設值。我找不到明顯的方法來做到這一點,因為我不想將巨集設定為全域鍵值選項,因為使它們全域化會以各種方式使事情變得複雜。我想要的只是將相關的鍵值保存到全域令牌列表中,以便我可以重複使用它們。 (我不在乎它是否不是一個令牌列表 - 這似乎是顯而易見的選擇。)

看起來,我可以很好地保存布林值和逗號分隔的列表,但我在處理令牌列表時遇到了麻煩,這些令牌列表本身就是鍵值選項列表。例如,graphics={<key-value options>}用於將設定傳遞給\includegraphics.但是,我無法讓它發揮作用。

這是一個(相對)最小的例子,這使得我完全不明白為什麼在金星上我試圖這樣做,但這對你來說是小型化。

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

錯誤訊息建議我向人類尋求幫助,所以我在這裡...

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

?   

如果我在嘗試使用令牌列表之前顯示它,我會得到

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

這表明我的頭腦簡單,我需要以某種方式在列表周圍包含大括號。然而,到目前為止,我的嘗試尚未成功。要么 LaTeX 尋找一些不應該成為鍵的東西(例如\g_pre_img_options),要么括號就消失了。

答案1

我不完全理解你想要實現的目標,無論我猜測什麼,我認為我不會以同樣的方式去做,但是,無論如何,這裡有一個使該文檔編譯的更改。

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

這似乎是錯誤的,即使我不清楚,也就是說,一方面,使許多不同部分的問題變得過於複雜,而且事實上你實際上無法做到這一點(添加\c_left_brace_str不是添加一個開放組catcode 1{而是添加一個catcode“其他”,類似於\string{)。透過簡單的x論證和正確的\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 } } , }
   }
 }

透過此更改,它至少可以編譯,但我不知道這是否可以解決所有問題。


您想要將一個字串和一個巨集的值新增到另一個巨集。最簡單的方法就是透過一個參數一次完成所有事情x。它實際上是在做你想做的事情,但是是正確的。\tl_put_right:Nx展開 an 中的第二個參數\edef,即展開一切,因此您只需在您想要的精確時刻停止即可。替換參數後,您以

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

如果您看到了,\edef\foo{graphics={foo}}您就會明白 的內容是什麼\foo:沒有任何內容擴展,字母也沒有,“其他”(“=”)也沒有,大括號{和 也沒有}。所以魔法就在裡面\exp_not:v { l_pre_grahpics_tl }。感謝 expl3 參數,它與\exp_not:V \l_pre_grahpics_tlwhich 完全相同,而後者\exp_not:n { width=\textwidth }只是停止擴展 ( \exp_not:nis \unexpanded)。

這樣,上面的行在x擴充之後就完全是

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

如果不是\unexpanded{width=\textwidth}TeX 可能會嘗試像任何其他巨集一樣進行擴展\textwidth,(現在不確定)可能會擴展為\dimen <number>,一般來說,我們不希望發生這種擴展。

抱歉,但任何人都可以自由編輯這個答案,這絕對不是完美的。

相關內容