假设我想编写一个命令igtest
,其工作方式与\includegraphics
来自相同graphicx
,不同之处在于如果给出了页码,例如\igtest[page=5]{someimg}
,则页码将被 1 覆盖,即它应该像一样工作\includegraphics[page=1]{someimg}
。(这是一个 MWE,所以不要问我为什么要这样做……)
我的尝试如下:
\documentclass{article}
\usepackage{graphicx}
\ExplSyntaxOn
\keys_define:nn { ig_keys } {
page.tl_set:N = \l_ig_page_tl
}
\tl_new:N \l__ig_unknown_keys_tl
\NewDocumentCommand{\igtest}{O{} m}
{
\keys_set_known:nnN { ig_keys }{ #1 }\l__ig_unknown_keys_tl
\tl_if_empty:NTF{\l_ig_page_tl}{
\includegraphics[#1]{#2}
}{
\includegraphics[\tl_use:N\l__ig_unknown_keys_tl,page=1]{#2}
}
}
\ExplSyntaxOff
\begin{document}
\igtest[width=\textwidth,page=2]{example-image-a}
\end{document}
路线图很明确:单独捕获页面密钥,将其他密钥作为未知密钥存储在令牌列表中\l__ig_unknown_keys_tl
,然后将其转发给\includegraphics
。
代码不起作用。显然,我没有\l__ig_unknown_keys_tl
正确使用。
如何修复?或者可以修复吗(因为\includegraphics
不是用 LaTeX3 编写的)?
答案1
使用\use:x
:
\documentclass{article}
\usepackage{graphicx}
\ExplSyntaxOn
\keys_define:nn { ig_keys } {
page.tl_set:N = \l_ig_page_tl
}
\tl_new:N \l__ig_unknown_keys_tl
\NewDocumentCommand{\igtest}{O{} m}
{
\keys_set_known:nnN { ig_keys }{ #1 }\l__ig_unknown_keys_tl
\tl_if_empty:NTF{\l_ig_page_tl}{
\includegraphics[#1]{#2}
}{
\use:x{
\exp_not:N\includegraphics[\exp_not:V \l__ig_unknown_keys_tl,page=1]{\exp_not:n{#2}}
}
}
}
\ExplSyntaxOff
\begin{document}
\igtest[width=\textwidth,page=2]{example-image-a}
\end{document}
这会构建一些要执行的代码(作为参数中的 x 扩展),然后执行它。(要打印出实际执行的代码,只需更改\use:x
为\tl_show:x
或类似内容。)
答案2
您可以定义 的内部副本\includegraphics
,因此您可以定义其变体。
\documentclass{article}
\usepackage{graphicx}
\ExplSyntaxOn
\keys_define:nn { ig_keys }
{
page.tl_set:N = \l_ig_page_tl,
}
\tl_new:N \l__ig_unknown_keys_tl
\cs_new_protected:Nn \__ig_ig:nnn { \includegraphics[#1,#2]{#3} }
\cs_generate_variant:Nn \__ig_ig:nnn { V }
\NewDocumentCommand{\igtest}{O{} m}
{
\group_begin:
\keys_set_known:nnN { ig_keys }{ #1 } \l__ig_unknown_keys_tl
\tl_if_empty:NTF \l_ig_page_tl
{
\__ig_ig:nnn { #1 } { } { #2 }
}
{
\__ig_ig:Vnn \l__ig_unknown_keys_tl { page=1 } { #2 }
}
\group_end:
}
\ExplSyntaxOff
\begin{document}
\igtest[width=3cm,angle=30,page=2]{example-image-a}
\igtest[width=3cm,angle=30]{example-image-a}
\end{document}
请注意,除非您首先清除的可能值,否则您需要\group_begin:
和。\group_end:
\l_ig_page_tl
更加紧凑:
\ExplSyntaxOn
\keys_define:nn { ig_keys }
{
page.tl_set:N = \l_ig_page_tl,
}
\tl_new:N \l__ig_unknown_keys_tl
\cs_new_protected:Nn \__ig_ig:nnn { \includegraphics[#1,#2]{#3} }
\cs_generate_variant:Nn \__ig_ig:nnn { Ve }
\NewDocumentCommand{\igtest}{O{} m}
{
\group_begin:
\keys_set_known:nnN { ig_keys }{ #1 } \l__ig_unknown_keys_tl
\__ig_ig:Ven \l__ig_unknown_keys_tl { \tl_if_empty:NF \l_ig_page_tl { page=1 } } { #2 }
\group_end:
}
\ExplSyntaxOff
答案3
您的问题与扩展有关(\includegraphics
在传入键时“看不到”它们,而只能看到\tl_use:N\l__ig_unknown_keys_tl,page=1
,因此尝试将其解析\tl_use:N\l__ig_unknown_keys_tl
为单个键,但失败了),并且用户202729 的回答展示如何修复该问题(通过在扩展\l__ig_unknown_keys_tl
之前扩展其值\includegraphics
)。
以下使用expkv-cs
替代方法来实现该过滤行为,这样就根本不需要扩展技巧了。但请注意,此机制仅适用于您想要以这种方式过滤的最多 8 个键(否则您将需要另一个宏,这expkv-cs
可能再次需要扩展技巧……)。
\documentclass{article}
\usepackage{expkv-cs}
\usepackage{graphicx}
\ExplSyntaxOn
\NewDocumentCommand \igtest {O{} m} { \__ig_test_filter_page:nn {#1} {#2} }
\ekvcSplit \__ig_test_filter_page:nn
{
page=, % #1 will be the value of the page key, and empty if it was unused
... % #2 will be all the unknown keys
}
{
\tl_if_empty:nTF {#1}
{ \includegraphics [#2] }
{ \includegraphics [#2, page=1] }
% the mandatory argument to \includegraphics will be curried
}
\ExplSyntaxOff
\begin{document}
\includegraphics[width=5cm, page=1]{example-image-duck}
\includegraphics[width=5cm, page=5]{example-image-duck}
\igtest[width=5cm, page=5]{example-image-duck}
\end{document}
小问题:由于它扩展为不可扩展的宏,因此\__ig_test_filter_page:nn
不会被定义,尽管它应该被定义。\protected
\includegraphics