我想编写一个宏(使用 Latex3/expl3),可以使用几个键值参数自动引用图。这是我目前拥有的:
\keys_define:nn{label}{
Re .tl_set:N = \l_label_Re_tl,
DOF .tl_set:N = \l_label_DOF_tl,
statsName .tl_set:N = \l_label_statsName_tl,
}
\NewDocumentCommand{\getProjOneLabel}{m}{
\keys_set:nn{label}{#1}
\newcommand{\Stat}{\StrLeft{\l_label_statsName_tl}{3}} %1st 3 letters of
fig:{\Stat}Re\l_label_Re_tl DOF\l_label_DOF_tl
}
当我用以下方法测试它时:
label=\getProjOneLabel{statsName=Strouhal,DOF=4M, Re=50}
它显示:
label=fig:StrRe50DOF4M
这是正确的。但是当我使用它进行实际引用时,如下所示:
\ref{\getProjOneLabel{statsName=Strouhal,DOF=4M, Re=50}}
而不是输出中的引用,如下所示:
??fig:StrRe50DOF4M
我认为这与扩展顺序有关,但我还不完全理解扩展过程。尝试了\expandafter
很多次,仍然失败。smbd 能否一步一步解释这里出了什么问题?当我将标签硬编码为
\ref{fig:StrRe50DOF4M}
它确实有效。目标是编写一个宏,比如“\plotref”,它将执行
\ref{\getProjOneLabel{statsName=Strouhal,DOF=4M, Re=50}}
其中所有 RHS 值都将作为键值参数传递。我是 Latex3 的新手,甚至对常规 Latex/Tex 也是新手,越详细越好。非常感谢。
更新:下面是基于 egreg 示例的测试代码。我从标签中删除了冒号以简化故障排除。当我注释行时
\tl_set:Nx \l_mylabel_tl{ \getProjOneLabel{#1} }
并取消注释
%\tl_set:Nx \l_mylabel_tl{StrRe50DOF4M}
有用。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\keys_define:nn { label }
{
Re .tl_set:N = \l_label_Re_tl,
DOF .tl_set:N = \l_label_DOF_tl,
statsName .tl_set:N = \l_label_statsName_tl,
Re .value_required:n = true,
DOF .value_required:n = true,
statsName .value_required:n = true,
}
\NewDocumentCommand{\getProjOneLabel}{m}{
\keys_set:nn{label}{#1}
%fig \c_colon_str
Str Re\l_label_Re_tl DOF\l_label_DOF_tl
}
\NewDocumentCommand{\keyref}{m}
{
%\keys_set:nn { label } { #1 }
\tl_new:N \l_mylabel_tl
%\tl_set:Nx \l_mylabel_tl{StrRe50DOF4M}
\tl_set:Nx \l_mylabel_tl{ \getProjOneLabel{#1} }
\\ label=\l_mylabel_tl \\ %checking label
Reference~ \ref{ \l_mylabel_tl }
}
\ExplSyntaxOff
\begin{document}
\section{X}
\label{StrRe50DOF4M} % just to experiment
\keyref{statsName=Strouhal,DOF=4M,Re=50} (should be 1)
\end{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 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
如果 smbd 想要继续执行此操作以绘制宏,则新线程在这里: 带有生成标签的图片的宏
答案1
\ref
应该传递完全扩展为字符串的内容,而不是构建字符串的指令。
因此,首先您必须设置密钥,然后才能以所需的方式将它们传递给。和\ref
之间可以共享相同的代码。\keyref
\keylabel
\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}
答案2
您的\getProjOneLabel
代码不是完全可扩展的,因为\newcommand
其中有(即赋值)。您可以通过\message
原始代码尝试“完全可扩展性”:
\message{LABEL=\getProjOneLabel{statsName=Strouhal,DOF=4M, Re=50}}
LABEL=fig:StrRe50DOF4M
它会在终端上打印结果。
我不喜欢 expl3 编程,所以我的解决方案仅使用 TeX 原语:
\def\getProjOneLabel#1{fig:\gpName#1,\end Re\gpRe#1,\end DOF\gpDOF#1,\end}
\def\gpName#1statsName=#2#3#4#5\end{#2#3#4}
\def\gpRe#1Re=#2,#3\end{#2}
\def\gpDOF#1DOF=#2,#3\end{#2}
\message{LABEL=\getProjOneLabel{statsName=Strouhal,DOF=4M, Re=50}}