\ref 使用宏作为参数

\ref 使用宏作为参数

我想编写一个宏(使用 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}

enter image description here

答案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}}

相关内容