从输入文件中“相对化”引用?

从输入文件中“相对化”引用?

我正在尝试找出一种方法来获取包含参考文献的输入 .tex 文件,但此参考文献的目标部分取决于 .tex 文件的包含位置。我想要的是让内部 PDF 超链接发挥作用,因此仅仅打印出正确的参考编号是不够的,实际参考文献本身也需要适合超链接。

这是一个简单的例子:

\documentclass{article}
\usepackage{hyperref}

\begin{document}

\section{Section One}
\label{sec:one}

\subsection{Subsection One One}
\label{subsec:one:one}

% First instance of input.tex
\input{input.tex}

\subsection{Subsection One Two}
\label{subsec:one:two}

\section{Section Two}
\label{sec:two}

\subsection{Subsection Two One}
\label{subsec:two:one}

% Second instance of input.tex
\input{input.tex}

\subsection{Subsection Two Two}
\label{subsec:two:two}

\end{document}

是否可以在 input.tex 文件中有一个引用指向第 X Two 子节,其中 X 是 input.tex 文件插入到的部分?类似于:

% contents of input.tex
Lorem ipsum blah blah blah, as described in \ref{sub{\thesection}:two}.

当然,这实际上不起作用,因此我的问题就出现了。但目的是让某个东西在第一个实例中解析为它包含在主文档中,但在第二个实例中\ref{subsec:one:two}解析为。\ref{subsec:two:two}

以防万一我的方法完全错误,并且有更简单的方法可以完成我正在尝试做的事情:从大局来看,我正在尝试构建一个构建块库。我正在构建一些文档,其中有一些可以隔离出来的片段,这些片段对于多台设备是相同的。我想使用这些片段来整理每台设备的文档,以获得它们的共同部分,以确保一致性并易于更新。但我希望这些片段能够在每个设备部分的范围内相互引用。整个文档将涵盖多台设备,并始终使用这些重复的片段。

编辑于 2022-07-03: \ref{sub\thesection:two}与我想要的非常接近,除了\thesection解析为数字,导致对sub1:two或的(非功能性)引用sub2:two,而不是预期的subsec:one:twosubsec:two:two。 有没有命令可以代替它,\thesection它会给我当前部分标签的实际文本而不是数字表示? 例如,sec:one而不是1

编辑于 2022-07-04:我离解决方案更近了一步,并进行了一些重构,input.tex现在可以使用文件内容进行内联:

\documentclass{article}
\usepackage{hyperref}
\usepackage{xstring}

\begin{filecontents*}[overwrite]{input.tex}
 This should be a reference to \ref{sub\parentlabel:two}, but it doesn't work.
\end{filecontents*}

% Saves a copy of the desired label in \currentlabel, then makes a \label with it
% as normal I would have preferred to do this by changing the behavior of \label
% itself, but I ran into even more roadblocks there which are not really in the
% scope of this question.
\newcommand{\clabel}[1]{%
    \def\currentlabel{#1}%
    \label{#1}
}

% The substring of \currentlabel between the first 'sub' and the last ':'.  In
% the absence of some better way to retrieve the current section/subsection/etc
%label, I can live with having to follow a strict naming scheme for this to work.
\newcommand{\parentlabel}{%
    \StrCount{\currentlabel}{:}[\lastcolon]%
    \StrBetween[1,\lastcolon]{\currentlabel}{sub}{:}
}

\begin{document}

\section{Section One}
\clabel{sec:one}

\subsection{Subsection One One}
\clabel{subsec:one:one}

% Saved copy of the current label, from using \clabel in place of \label
The current label is: \currentlabel

% Substring with the label of the parent (assuming my naming convention is used)
The parent of the current label is: \parentlabel

% Prepend 'sub' and append ':two' to create the desired reference
The desired reference is: sub\parentlabel:two

% But \ref will not accept this argument.  Uncomment the following line, and
% errors will occur.
%This should be a reference to \ref{sub\parentlabel:two}, but it doesn't work.

% Likewise if it is brought in from an external file, which it ultimately will
% be.  But I don't think that's pertinent to why it isn't working.
% First instance of input.tex
%\input{input.tex}

\subsection{Subsection One Two}
\clabel{subsec:one:two}

The current label is: \currentlabel

The parent of the current label is: \parentlabel

The desired reference is: sub\parentlabel:two

\section{Section Two}
\clabel{sec:two}

\subsection{Subsection Two One}
\clabel{subsec:two:one}

The current label is: \currentlabel

The parent of the current label is: \parentlabel

The desired reference is: sub\parentlabel:two

% Second instance of input.tex
%\input{input.tex}

\subsection{Subsection Two Two}
\clabel{subsec:two:two}

The current label is: \currentlabel

The parent of the current label is: \parentlabel

The desired reference is: sub\parentlabel:two

\end{document}

我觉得\expandafter某个地方可能需要一个,但我尝试将它放在任何地方都只会导致不同的错误。此外,这感觉是一种相当不优雅的做法,弄乱了子字符串等,但希望它至少说明了我正在尝试做的事情。

编辑 2022-07-07:成功!A.Ellett 的建议让我在 pgfkeys 方面找到了正确的方向,所以我将把它标记为解决方案(我非常感谢您的帮助)。我阅读了一些关于 pgfkeys 的内容,并建立了一些我能理解的东西(我对 LaTeX 还很陌生),希望能向其他可能处理这些文档的人解释。

我做了一套新的\sect与不同子级\section命令相对应的新命令,它们接受两个参数。一个作为名称传递给普通\section命令,另一个用作“标记”以根据我的命名约定构建标签。这样,我可以在实际名称中更加详细和描述性,但标签名称更短且没有空格。然后,该命令设置与层次结构级别相对应的 pgfkey,以匹配它刚刚设置的标签,然后清除层次结构中较低的任何 pgfkeys。还有一组\currentsec用于不同子级的命令,以方便读取 pgfkeys。

可能有一种更优雅的方法来实现这一点,即使用实际的 pgfkeys 层次结构,而不是像我在这里所做的那样覆盖相同的三个键。但就我的目的而言,能够引用当前 (sub)(sub) 部分就足够了。任何无法通过这些方法实现的引用,可能更适合在主文档中一次性实现,而不是在我的可重复使用的代码片段中。

我的工作示例文档如下。它显示了层次结构中每个级别的 pgfkeys 的值,演示了 input.tex 中一个以我想要的方式“上下文感知”的引用。它还添加了另一个引用,只是为了与其他层次结构级别进行交互。还有一些方便的命令可以减少所有重复的总体大小,希望它仍然足够清楚发生了什么。

我确实对部分名称进行了一些改写,以便更好地区分层次结构的不同级别。事后看来,我可能因为在层次结构的每个级别都使用ones 和s 而混淆了这个问题。two

\begin{filecontents*}[overwrite]{input.tex}
      Reference to subsection Two of current section: \ref{sub\currentsec:two}
\end{filecontents*}

\documentclass{article}
\usepackage{hyperref}
\usepackage{pgfkeys}

% Use in place of \section.  Arg 1 is name that you would use for
% \section.  Arg 2 is short name for building up the label.
\newcommand{\sect}[2]{%
    \section{#1}%
    \label{sec:#2}%
    \pgfkeyssetvalue{/currentsec}{sec:#2}
    \pgfkeyssetvalue{/currentsubsec}{}
    \pgfkeyssetvalue{/currentsubsubsec}{}
}

% Ditto, but for \subsection.
\newcommand{\subsect}[2]{%
    \subsection{#1}%
    \label{sub\currentsec:#2}%
    \pgfkeyssetvalue{/currentsubsec}{sub\pgfkeysvalueof{/currentsec}:#2}
    \pgfkeyssetvalue{/currentsubsubsec}{}
}

% Ditto, but for \subsubsection.
\newcommand{\subsubsect}[2]{%
    \subsubsection{#1}%
    \label{sub\currentsubsec:#2}%
    \pgfkeyssetvalue{/currentsubsubsec}{sub\pgfkeysvalueof{/currentsubsec}:#2}
}

% Convenience command for brevity and legibility.
\newcommand{\currentsec}{%
    \pgfkeysvalueof{/currentsec}%
}

% Ditto.
\newcommand{\currentsubsec}{%
    \pgfkeysvalueof{/currentsubsec}%
}

%Ditto.
\newcommand{\currentsubsubsec}{%
    \pgfkeysvalueof{/currentsubsubsec}%
}

% Convenience command to cut down document size from repetition.
\newcommand{\showvalues}{%
Current section: \currentsec

Current subsection: \currentsubsec

Current subsubsection: \currentsubsubsec
}

\begin{document}

\sect{Blue}{blue}

\showvalues

\input{input.tex}

\subsect{Blue One}{one}

\showvalues

\input{input.tex}

Reference to subsubsection Alpha of current subsection: \ref{sub\currentsubsec:alpha}

\subsubsect{Blue One Alpha}{alpha}

\showvalues

\input{input.tex}

\subsect{Blue Two}{two}

\showvalues

\input{input.tex}

\sect{Red}{red}

\showvalues

\input{input.tex}

\subsect{Red One}{one}

\showvalues

\input{input.tex}

\subsubsect{Red One Bravo}{bravo}

\showvalues

\input{input.tex}

\subsect{Red Two}{two}

\showvalues

\input{input.tex}

\end{document}

答案1

我一直在想弄清楚你想要什么。我仍然有点不确定。

我确实有顾虑。但我将在回答结束时提出这些问题,或者更确切地说,在开始更深入的对话时提出这些问题。我给出了一个替代方案更深入的对话因为我可能没有抓住重点。

这是一个编译好的例子:

在此处输入图片描述

它是用以下代码创建的:

%% --------------------------------------------------
\begin{filecontents*}[overwrite]{snippet_01}
      The \emph{primary assumption}(\ref{\GetLabelName{A}})
      I make is that you want the labels to be renamed
      according to the section or subsection the snippet is
      input from.  So you can reference them from some place
      else in the document.
\end{filecontents*}
%% --------------------------------------------------
%% example input file #2                             
%% --------------------------------------------------
\begin{filecontents*}[overwrite]{snippet_02}
      The \emph{other detail}(\ref{\GetLabelName{B}})
      that you seem to want is to have the labels be sensitive
      to their context within the sectioning and subsectioning
      hierarchy.
\end{filecontents*}
%% --------------------------------------------------
%% example input file #3                             
%% --------------------------------------------------
\begin{filecontents*}[overwrite]{snippet_03}
      \begin{equation}
          \mathrm{e}^{i\pi} = -1 \label{\GetLabelName{E}}
      \end{equation}
\end{filecontents*}
%% --------------------------------------------------
%% end of example input files                        
%% --------------------------------------------------
\documentclass{article}
%% --------------------------------------------------
%% I use `pgfkeys` to manage the references/labels   
%% that are inside the input files.                  
%% --------------------------------------------------
\usepackage{pgfkeys}

\makeatletter
\providecommand\aesnippetpath{}

\newcommand\SetLabelName[2]{%%
  \expandafter\providecommand\csname aesnippetref#1\endcsname{}%%
  \expandafter\renewcommand\csname aesnippetref#1\endcsname{#2}}

\newcommand\GetLabelName[1]{%%
  \csname aesnippetref#1\endcsname}

\pgfkeys{/ae/snippet/refs/.cd,
  ref a/.code={\SetLabelName{A}{#1}},
  ref b/.code={\SetLabelName{B}{#1}},
  ref c/.code={\SetLabelName{C}{#1}},
  ref d/.code={\SetLabelName{D}{#1}},
  ref e/.code={\SetLabelName{E}{#1}},
   path/.code={\def\aesnippetpath{#1}},
  }

\newcommand\snippet[1][]{%%
  \pgfkeys{/ae/snippet/refs/.cd,#1}%%
  \input{\aesnippetpath}%%
  }

\makeatother

\begin{document}

%-@-(1)--------------------------------------------
\section{Section One}%%

  \label{sec:one}%%
  I'm not entirely clear on how you want these labels and
  references to work.  So, here I illustrate a variety of
  labels and references:  in the main documents and others
  nestled inside \emph{snippets} of code that may be reused.
  \begin{enumerate}
  \item
  \snippet[ref a=sec:one,
           path=snippet_01]%%
  \item
  \snippet[ref b=sec:one,
           path=snippet_02]%%
  \end{enumerate}
  I have a number of questions.  But, I'll raise those in
  section~\ref{questions}. 

\subsection{sub:one:one}

  \label{sub:one:one}%%
  There are a number of approaches you could take.  I happen to
  like the idea present by \emph{Ulrike Fischer}.  And there is
  some similarity here with that.  Somehow a label created
  within your subsection needs to be identified.

  So let's reconsider what my assumptions are.
  The first assumption was:
  \begin{itemize}
  \item  \snippet[ref a=sub:one:one,
                  path=snippet_01,
                 ]
  \end{itemize}
  and that's what I've done here.  I created a label within the
  section.  Then I input my \emph{snippet} of code and it is
  able to correctly identify.

  And, I've nailed the sensitivity to context: 
  \begin{itemize}
  \item \snippet[ref b=sub:one:one,
                 path=snippet_02,
                ]
  \end{itemize}

\section{Section Two}

  \label{questions}%%
  If you wish, you can also use the same approach to define a
  label within your inputted code:

  \snippet[ref e=sec:two:equation,
           path=snippet_03]

  And I can refer to this as equation~(\ref{\GetLabelName{E}}).

%-#-{a}--------------------------------------------
\subsection{Sub:Two:One}

  \label{sub:two:one}
  Now I'm in another subsection,
  
  \snippet[ref e=sub:two:one:equation,
           path=snippet_03]

  And I can easily refer to either equation~(\ref{sec:two:equation})
  or equation~(\ref{sub:two:one:equation}) even though it's the
  same input file with the same code.

\end{document}
    
        

基本思想是提供一个包装器\input{...}使你能够追踪标签。有几种方法可以做到这一点。您可以通过定义一组宏来为您完成这项工作。我选择使用来控制我正在做的事情。只要你有适当的代码输入文件,这应该相当灵活。使用相同的代码,您仍然可以与它交互,就好像它允许在文本中遇到不同的标签/引用(嗯,实际上我的代码实现了这一点)。

您遇到的问题之一是可扩展性问题,手册确实xstring警告过这是一个潜在问题。我不是该领域的专家。所以,我放弃了这个xstring包,自己想办法解决。

担忧和困惑

我感到困惑的是,每个小节都需要重新调整参考/标签。从我的角度来看,重要的是第一次引入附加文本。

我首先担心的是:在重复文本时可能没关系,多次引用同一篇文章但引用文档中的不同展示点可能会让读者感到困惑。读者可能会感到困惑,认为一定有什么变化,也许是微妙的变化,需要不同的标签/引用。为什么不直接说,“在第 5 页我们首先介绍了以下想法,我们在这里重复一下以便于参考”?

我的第二个担忧是:任何篇幅过长的内容都会变得重复,要么让读者感到厌烦,要么让读者感到无聊。他们会不再密切关注你写的内容,因为你重复了太多次。一个简短的片段,比如一个值得提醒读者的方程式(即使它之前已经介绍过)就可以了。但正如我上面提到的,保留原始标签似乎更合适。

答案2

假设您确实只想要当前小节,那么类似这样的操作应该可以工作:

\documentclass{article}
\usepackage{hyperref}

\begin{document}

\section{Section One}
\label{sec:one}

\subsection{Subsection One One}
\label{subsec:one:one}


\hyperlink{subsection.\theHsubsection}{\thesubsection}


\subsection{Subsection One Two}
\label{subsec:one:two}

\section{Section Two}
\label{sec:two}

\subsection{Subsection Two One}
\label{subsec:two:one}

\hyperlink{subsection.\theHsubsection}{\thesubsection}
\subsection{Subsection Two Two}
\label{subsec:two:two}

\end{document}

相关内容