再会,
我想编写一个宏(使用 Latex3/expl3)来发布图片并可以为生成的标签/标题等获取几个键值参数。我已经找到了可以做到这一点的代码,但传递生成的标签不起作用。
它从这个线程开始: \ref 使用宏作为参数
这是采用通用键值参数来放置图的宏代码(如果我使用带有硬编码标签的 \addpic 则有效):
%usage example
% \addpic{
% width=0.3,
% image=example-image,
% caption={This is an example image, and a comma in the caption},
% label=one,
% }
% \addpic{
% placement=bp,
% width=0.2,
% options={angle=90},
% image=example-image-a,
% caption=Rotated image,
% shortcaption=In the text the image is rotated!,
%}
\ExplSyntaxOn
% the user level command
\NewDocumentCommand{\addpic}{m}
{
\group_begin: % localize the changes to the variables
\simonson_pic:n { #1 }
\group_end:
}
% the key-value interface
\keys_define:nn { simonson/pic }
{
placement .tl_set:N = \l_simonson_pic_placement_tl,
placement .initial:n = htp,
width .tl_set:N = \l_simonson_pic_width_tl,
width .initial:n = 1,
options .tl_set:N = \l_simonson_pic_options_tl,
image .tl_set:N = \l_simonson_pic_image_tl,
caption .tl_set:N = \l_simonson_pic_caption_tl,
shortcaption .tl_set:N = \l_simonson_pic_shortcaption_tl,
label .tl_set:N = \l_simonson_pic_label_tl,
}
% the main command
\cs_new_protected:Nn \simonson_pic:n
{
% set the keys from the argument
\keys_set:nn { simonson/pic } { #1 }
% start the figure environment
\__simonson_start_figure:V \l_simonson_pic_placement_tl
\centering
% include the image
\__simonson_pic_image:VVV
\l_simonson_pic_width_tl % the text width fraction
\l_simonson_pic_options_tl % other options
\l_simonson_pic_image_tl % the image name
% the caption
\tl_if_empty:NTF \l_simonson_pic_shortcaption_tl
{
\caption{\l_simonson_pic_caption_tl}
}
{
\caption[\l_simonson_pic_shortcaption_tl]{\l_simonson_pic_caption_tl}
}
% the label
In \ addpics \ macro:\ label=\l_simonson_pic_label_tl %for test(my code)
\tl_if_empty:NF \l_simonson_pic_label_tl
{
\label{\l_simonson_pic_label_tl}
}
% end the figure environment
%### %for parser to ignore
\end{figure}
%###
}
% syntactic sugar: we want some token lists to be expanded before usage
\cs_new_protected:Nn \__simonson_start_figure:n
{
\begin{figure}[#1]
}
\cs_generate_variant:Nn \__simonson_start_figure:n { V }
\cs_new_protected:Nn \__simonson_pic_image:nnn
{
\includegraphics[width=#1\textwidth,#2]{#3}
}
\cs_generate_variant:Nn \__simonson_pic_image:nnn { VVV }
\ExplSyntaxOff
关键要求是生成标签的代码位于一个地方(作为宏),因为我需要引用生成的标签,并且在使用多个键值参数引用时将使用相同的代码。
以下是 egreg 在第一个主题中提出的建议(尽管我并没有在那里指出最终目标):
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\keys_define:nn { strider/label }
{
Re .tl_set:N = \l_strider_label_Re_tl,
DOF .tl_set:N = \l_strider_label_DOF_tl,
statsName .tl_set:N = \l_strider_label_statsName_tl,
Re .value_required:n = true,
DOF .value_required:n = true,
statsName .value_required:n = true,
}
\NewDocumentCommand{\keyref}{m}
{
\strider_label:Nn \ref { #1 }
}
\NewDocumentCommand{\keylabel}{m}
{
\strider_label:Nn \label { #1 }
}
\cs_new_protected:Nn \strider_label:Nn
{
\keys_set:nn { strider/label } { #2 }
#1 % will be \label or \ref
{
fig \c_colon_str
\tl_item:Nn \l_strider_label_statsName_tl { 1 }
\tl_item:Nn \l_strider_label_statsName_tl { 2 }
\tl_item:Nn \l_strider_label_statsName_tl { 3 }
Re \l_strider_label_Re_tl DOF \l_strider_label_DOF_tl
}
}
\ExplSyntaxOff
\begin{document}
\section{X}
\keylabel{statsName=Strouhal,DOF=4M, Re=50} % just to experiment
This gives a number: \keyref{statsName=Strouhal,DOF=4M, Re=50} (should be 1)
\end{document}
这确实有效,尽管不知道如何使用 \keylabel 将标签作为参数传递给 \addpic。 \addpic 宏将很少在文档级别使用(而不是在生成标签和标题的其他宏中使用),因此我希望尽可能保持它的通用性。文档级宏:示例调用:
\myplotFF{file={\plotsPathReFifty/StrouhalNumber},Re=50,DOF=4M, statsName=Drag}
宏:
\keys_define:nn{myPlot}{
Re .tl_set:N = \l_myPlot_Re_tl,
DOF .tl_set:N = \l_myPlot_DOF_tl,
statsName .tl_set:N = \l_myPlot_statsName_tl,
file .tl_set:N = \l_myPlot_file_tl,
height .tl_set:N = \l_myPlot_height_tl,
label .tl_set:N = \l_myPlot_label_tl,
path .tl_set:N = \l_myPlot_path_tl
}
\NewDocumentCommand{\myplotFF}{m}{
\keys_set:nn{myPlot}{#1}
\addpic{
width=0.6,
%height=0.6,
image=\l_myPlot_file_tl,
caption=\getCaption{statsName=\l_myPlot_statsName_tl,
DOF=\l_myPlot_DOF_tl,
Re=\l_myPlot_Re_tl},
label=\keylabel{statsName=\l_myPlot_statsName_tl,DOF=\l_myPlot_DOF_tl,Re=\l_myPlot_Re_tl},
}
}
当然,带有“label=...”的行不起作用,但如果我传递一个硬编码的标签,它就起作用了。这就是第一个线程的全部内容。谢谢!
答案1
如果我理解正确,那么你需要以下输入
\section{X}
\myplotFF{file={example-image-a},Re=50,DOF=4M, statsName=Drag}
产生以下输出
您目前拥有的代码很乱。您似乎为一个包/类/设置了多个模块,并为处理相同的选项/数据设置了多个子模块。这不是一个好策略。 expl3 语法的重点是一致性,而混乱的键值对集合的大杂烩会导致代码极不一致。
请注意,这并不是对原始答案的批评。相反,这是由于试图将相关功能的完全不同的实例相互抛出,希望事物能够结合在一起形成一个和谐的整体而产生的一个问题。这有点像让一群两岁的孩子在你的客厅里迷失,三四套协调得很好的油漆组合在一起时会非常不协调,并希望幼儿的审美感能将它们组合成一个令人愉悦的结果。问题不在于任何协调的配色方案,而在于试图用幼儿方法将它们组合起来。结果不会很漂亮。
我已将其标准化strider
为主模块,并strider/pic
作为唯一的子模块。我不确定子模块是否有用或必要,但我不知道大局是什么,所以也许是有原因的。
% arara: pdflatex
\pdfminorversion=7
\documentclass{article}
\usepackage{xparse,graphicx}
\ExplSyntaxOn
% the key-value interface
\keys_define:nn {strider/pic} {
Re .tl_set:N = \l_strider_label_Re_tl,
DOF .tl_set:N = \l_strider_label_DOF_tl,
statsName .tl_set:N = \l_strider_label_statsName_tl,
file .tl_set:N = \l_strider_file_tl,
height .tl_set:N = \l_strider_height_tl,
Re .value_required:n = true,
DOF .value_required:n = true,
statsName .value_required:n = true,
caption .tl_set:N = \l_strider_pic_caption_tl,
placement .tl_set:N = \l_strider_pic_placement_tl,
placement .initial:n = htp,
width .tl_set:N = \l_strider_pic_width_tl,
width .initial:n = 0.6,
options .tl_set:N = \l_strider_pic_options_tl,
shortcaption .tl_set:N = \l_strider_pic_shortcaption_tl,
}
\cs_new_protected:Nn \strider_label:N
{
#1 % will be \label or \ref
{
fig \c_colon_str
\tl_item:Nn \l_strider_label_statsName_tl { 1 }
\tl_item:Nn \l_strider_label_statsName_tl { 2 }
\tl_item:Nn \l_strider_label_statsName_tl { 3 }
Re \l_strider_label_Re_tl DOF \l_strider_label_DOF_tl
}
}
% the main command
\cs_new_protected:Nn \strider_pic:
{
% start the figure environment
\__strider_start_figure:V \l_strider_pic_placement_tl
\centering
% include the image
\__strider_pic_image:VVV
\l_strider_pic_width_tl % the text width fraction
\l_strider_pic_options_tl % other options
\l_strider_file_tl % the image name
% the caption
\tl_if_empty:NT \l_strider_pic_caption_tl
{
\tl_set:Nn \l_strider_pic_caption_tl
{
statsName:~\l_strider_label_statsName_tl,~DOF:~\l_strider_label_DOF_tl,~Re:~\l_strider_label_Re_tl
}
}
\tl_if_empty:NTF \l_strider_pic_shortcaption_tl
{
\caption{\l_strider_pic_caption_tl}
}
{
\caption[\l_strider_pic_shortcaption_tl]{\l_strider_pic_caption_tl}
}
\strider_label:N \label
% end the figure environment
%### %for parser to ignore
\end{figure}
%###
}
% syntactic sugar: we want some token lists to be expanded before usage
\cs_new_protected:Nn \__strider_start_figure:n
{
\begin{figure}[#1]
}
\cs_generate_variant:Nn \__strider_start_figure:n { V }
\cs_new_protected:Nn \__strider_pic_image:nnn
{
\includegraphics[width=#1\textwidth,#2]{#3}
}
\cs_generate_variant:Nn \__strider_pic_image:nnn { VVV }
\NewDocumentCommand{\myplotFF}{m}{
\group_begin:
\keys_set_known:nn { strider / pic } {#1}
\strider_pic:
\group_end:
}
\NewDocumentCommand{\keyref}{m}
{
\keys_set_known:nn { strider / pic } { #1 }
\strider_label:N \ref
}
\ExplSyntaxOff
\begin{document}
\section{X}
\myplotFF{file={example-image-a},Re=50,DOF=4M, statsName=Drag}
See figure \keyref{Re=50,DOF=4M, statsName=Drag}
\myplotFF{file={example-image-b},Re=48,DOF=4M, statsName=Drag,caption={Override caption in this case} }
See figure \keyref{Re=50,DOF=4M, statsName=Drag} and \keyref{Re=48,DOF=4M, statsName=Drag}
\end{document}
编辑
上面的代码经过编辑,以证明标签是已经自动生成了!为了展示这一点,我添加了一个稍微修改过的版本,\keyref
以便可以轻松地在输出中说明标签。
编辑 编辑
进一步编辑以简化一些并为标题提供可选的覆盖。