将动态文本与标签关联

将动态文本与标签关联

我正在尝试将一些文本(使用计数器动态生成)关联到标签,以便我可以引用该标签并打印相关文本(无需重新生成它,这会导致计数器出现问题)。

使用示例:

\textLabel{key}{\dynamicText}

之后,在文档的某个地方,我想要一个新的宏,链接到键并显示由 \dynamictext 生成的文本。

这个宏不太起作用:

\makeatletter
\newcommand{\textLabel}[2]{%
    \protected@edef\var{\expandafter\noexpand#2}%
    \label{#1}\var%
    \global\expandafter\def\csname#1\endcsname{\hyperref[#1]{\var}}%
}
\makeatother

\var似乎工作正常。问题是,用 标识的宏\#1在文档中不可见,并产生错误(未找到控制序列)。

我哪里做错了?


背景:我有一长串项目,需要以某种奇怪格式提供唯一 ID。我通过调用宏来自动生成列表中项目的 ID,该宏会增加一些计数器并根据计数器的值返回 ID。

现在,我想写入生成的 ID 并引用这些项目,而无需调用用于构建它们的宏。(这意味着以\getID相同的顺序和次数调用,我不想这样做)


这是一个最小(不)工作的例子:

\documentclass[11pt]{report}       

\makeatletter
\newcommand{\textLabel}[2]{%
    \protected@edef\var{\expandafter\noexpand#2}%
    \label{#1}\var%
    \global\expandafter\def\csname #1\endcsname{\hyperref[#1]{\var}}
}
\makeatother

\newcounter{req}
\newcommand{\getid}[1]{%
    \stepcounter{req}%
    #1.\arabic{req}%
} 

\begin{document}
    \begin{itemize}
        \item \textLabel{itemkeyone}{\getid{ITEM}}
        \item \textLabel{itemkeytwo}{\getid{ITEM}}
    \end{itemize}

    \itemkeyone %I want: ITEM.1, instead produces command not found
\end{document}  

这是一个最小的工作示例,但行为错误:

\documentclass[11pt]{report}       

\usepackage{hyperref}

\newcommand{\textLabel}[2]{%
    \label{#1}#2%
    \global\expandafter\def\csname#1\endcsname{\hyperref[#1]{#2}}
}


\newcounter{req}
\newcommand{\getid}[1]{%
    \stepcounter{req}%
    #1.\arabic{req}%
} 

\begin{document}
    \begin{itemize}
        \item \textLabel{itemkeyone}{\getid{ITEM}}
        \item \textLabel{itemkeytwo}{\getid{ITEM}}
    \end{itemize}

    \itemkeyone %I want: ITEM.1, instead produces ITEM.3
\end{document}  

非常感谢

答案1

这是一个完全不同的方法鍵盤。由于有这么多注释,代码比 Manuel 的要长,所以也许我不能声称它很简单,但我就是喜欢用 pgfkeys 来做这种事。

为了证明它的工作原理,下面是我的代码生成的结果: 在此处输入图片描述 ...代码如下:

\documentclass{article}
\usepackage{etoolbox}

\usepackage{pgfkeys}
\pgfkeys{/MyLabels/.is family, /MyLabels,
  % set labels using \pgfkeyssetvalue => can test with \pgfkeysifdefined
  % This allows arbitrary new keys to be defined on the fly
  .unknown/.code={\pgfkeyssetvalue{/MyLabels/\pgfkeyscurrentname}{#1}},
}

\newcounter{getID}% a dummy counter to imitate \getID

\newcommand\SetLabel[1]{% set label to current value of getID
  \stepcounter{getID}% might want \refstepcounter in real life
  Settting: #1 = ID\arabic{getID} %
  \pgfkeys{/MyLabels,#1/.expanded=ID\arabic{getID}}% force expansion
  (stored value: \pgfkeys{/MyLabels/#1}).
}
\newcommand\UseLabel[1]{% print label if it bas been defined
  Getting: #1 =
   \pgfkeysifdefined{/MyLabels/#1}%
      {\pgfkeysvalueof{/MyLabels/#1}}% print if defined
      {???}% question marks if not defined
  .%
}

\begin{document}

\SetLabel{first}

\SetLabel{second}

\UseLabel{first}

\UseLabel{second}

\UseLabel{first}

\end{document}

编辑:解决方案 II

我意识到这都是小题大做:你应该只使用 LaTeX 的\label\ref命令。当你创建标签时,会发生的情况是,当前的值\@currentlabel被写入辅助文件,然后在下一次编译时可以使用访问\ref。因此,如果你将\@currentlabel输出设置为,\getID那么你就完成了。但是,你不能将\@currentlabel等于设置为,\getID{item}因为\getID命令包含一些不可扩展的内容。相反,你应该将\getID设置设置为虚拟变量,或者更好的是,设置\@currentlabel

以下是根据您的 MWE 提出的第二个解决方案:

\documentclass[11pt]{report}

\newcommand\textLabel[2]{\getid{#2}\label{#1}}

\makeatletter
\newcounter{req}
\newcommand{\getid}[1]{%
    \stepcounter{req}%
    \def\@currentlabel{#1.\arabic{req}}%
}
\makeatother

\begin{document}
    \begin{itemize}
        \item \textLabel{itemkeyone}{ITEM}
        \item \textLabel{itemkeytwo}{ITEM}
    \end{itemize}

    \ref{itemkeyone} %I want: ITEM.1

    \ref{itemkeytwo} %I want: ITEM.1
\end{document}

由于这是在幕后使用,标签将从一次编译持续到下一次编译,但您需要对文档进行两次编译才能生效\label\ref

输出如下:

在此处输入图片描述

答案2

textlabels一种将伪造的标签写入文件然后.aux手动建立的风格。\hypertarget\hyperlink

\documentclass[11pt]{report}       

\usepackage{hyperref}


\newcounter{req}

\makeatletter
\newcommand{\textLabel}[2]{%
  \stepcounter{req}%
  \hypertarget{#1.\number\value{req}}{#2.\arabic{req}}%
  \immediate\write\@auxout{%
    \string\newlabel{#1.\number\value{req}}{{#2.\number\value{req}}{}{}{}{}} % Write the text label!
  }
  \expandafter\xdef\csname #1\endcsname{%
    \unexpanded{\hyperlink}{#1.\number\value{req}}{\getrefnumber{#1.\number\value{req}}}
  }
}
\makeatother


\begin{document}
\chapter{Foo} \label{foolabel}
    \begin{itemize}
        \item \textLabel{itemkeyone}{ITEM}
          \clearpage
        \item \textLabel{itemkeytwo}{ITEM}
    \end{itemize}

\clearpage
    \itemkeyone %I want: ITEM.1, instead produces ITEM.3

    \itemkeytwo
\end{document}  

在此处输入图片描述

答案3

我认为这是可行的,但还没有彻底测试过

\documentclass{scrartcl}

\usepackage{hyperref}

\newcounter{req}
\newcommand*\getid[1]{\def\thereq{#1.\arabic{req}}\refstepcounter{req}\thereq} 

\begin{document}

\begin{itemize}
  \item \getid{ITEM} \label{itemkeyone}
  \item \getid{ITEM} \label{itemkeytwo}
\end{itemize}
\ref{itemkeyone}

\end{document}

相关内容