我有一個使用鍵值語法的命令。例如,如果需要,它包括帶有各種選項的圖像。
我正在使用 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_tl
which 完全相同,而後者\exp_not:n { width=\textwidth }
只是停止擴展 ( \exp_not:n
is \unexpanded
)。
這樣,上面的行在x
擴充之後就完全是
\tl_gput_right:Nn \g_pre_img_options_tl { graphics = { width = \textwidth } , }
如果不是\unexpanded{width=\textwidth}
TeX 可能會嘗試像任何其他巨集一樣進行擴展\textwidth
,(現在不確定)可能會擴展為\dimen <number>
,一般來說,我們不希望發生這種擴展。
抱歉,但任何人都可以自由編輯這個答案,這絕對不是完美的。