0

I'm trying to figure out a way to have an input .tex file that contains a reference, but for the target of this reference to be partially based on where the .tex file is included. What I'm going for is to have the internal PDF hyperlinks be functional, so it's not enough simply to have the correct reference numbers printed out, the actual reference itself needs to be correct for the hyperlink.

Here's a stripped-down example:

\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}

Is it possible to have a reference in the input.tex file that will point to Subsection X Two, where X is the section the input.tex file is inserted into? Something like:

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

Although this doesn't actually work, of course, hence my issue. But the intent is to have something that resolves to \ref{subsec:one:two} in the first instance it is included in the main document, but that resolves to \ref{subsec:two:two} in the second instance.

And just in case I am completely wrong in my approach, and there is some way easier way to do what I'm trying to do: big-picture, I am trying to build out a library of building blocks. I am building some documentation where there are snippets that I can isolate out which are identical for multiple pieces of equipment. I'd like to put together the documentation for each piece of equipment using these snippets for the parts they have in common, both for consistency and for ease of updating. But I'd like the snippets to be able to refer to each other within the scope of each equipment's section. The entire document will cover multiple pieces of equipment, with these repeated snippets used throughout.

Edit 2022-07-03: \ref{sub\thesection:two} is tantalizingly close to what I'm going for, except \thesection resolves to a number, resulting in a (non-functional) reference to sub1:two or sub2:two, rather than the intended subsec:one:two or subsec:two:two. Is there a command I could use in place of \thesection that would give me the actual text of the current section's label instead of the numerical representation? E.g. sec:one instead of 1.

Edit 2022-07-04: I have inched even closer to a solution, and refactored a bit so that input.tex is now inline using filecontents:

\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}

I feel like probably an \expandafter is needed somewhere, but everywhere I tried to put it just resulted in a different batch of errors. Also, this feels like a pretty inelegant way of doing this, messing around with substrings and such, but hopefully it at least illustrates what I'm trying to do.

Edit 2022-07-07: Success! A.Ellett's suggestion got me pointed in the right direction with pgfkeys, so I'm going to mark that as the solution (and I really appreciate the assistance). I did some reading on pgfkeys and built up something that I can understand (I'm still quite new to LaTeX), and hopefully can explain to others who might work on these documents.

I made a new set of \sect commands corresponding to the different sub-levels of \section commands, and they take two arguments. One is passed along as the name to the normal \section command, and the other is used as a "token" to build the label up according to my naming convention. This way I can be more verbose and descriptive in the actual name, but have something shorter and with no spaces for the label. The command then sets the pgfkey corresponding to the hierarchy level, to match the label it just set, and then clears out any pgfkeys that are lower in the hierarchy. There is also a set of \currentsec commands for the different sub-levels, as a convenience to read the pgfkeys.

There is probably a more elegant way to do this using an actual hierarchy of pgfkeys rather than just overwriting the same three keys like I am doing here. But for my purposes, it's enough to be able to reference the current (sub)(sub)section. Any reference that can't be done with those, would probably be more appropriate to have as a one-off in the main document, rather than in my reusable snippets.

My working sample document is below. It displays what the values of the pgfkeys are at each level of the hierarchy, demonstrates a reference in the input.tex that is "context aware" in the way I wanted. It also has another reference thrown in there just to play around with the other hierarchy levels. And there are a few convenience commands to cut down on the overall size with all the repetition, hopefully it's still clear enough what's going on.

I did reword the section names a bit so that there is more distinction between the different levels of the hierarchy. In hindsight, I probably confused the issue by having ones and twos at every level of the hierarchy.

\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}
10
  • You could create a counter that is triggered every time you recompile the code from the input file. Then, you could create an conditional based on that counter to trigger the correct reference to be used.
    – A.Ellett
    Commented Jun 30, 2022 at 4:38
  • It seems like that would require me to know in advance, exactly how many times and in which order input.tex gets called from the various sections, and to hard-code in all the different references to be inserted. I'd like to preserve the flexibility of being able to add/remove sections and subsections, and it just dynamically adjusts accordingly when compiled. If we imagined the document structure like a directory tree, I am trying to do something analogous to making a relative path to "../something" or "../../something", rather than the full path "C:/directory/subdirectory/something".
    – Cameron L
    Commented Jun 30, 2022 at 22:42
  • Are you using a directory structure to determine how the references and sections are supposed to work? If you are, you could use currfile to access the directory path information.
    – A.Ellett
    Commented Jul 1, 2022 at 0:23
  • I think it's unclear what you're asking. I'd suggest creating a MWE that illustrates the point and then explain how you want the references to work.
    – A.Ellett
    Commented Jul 1, 2022 at 0:56
  • No, I only brought up directories as a commonly-understood example of a relative vs. an absolute reference. What I want is for the contents of input.tex to be able to contain a reference, but for that reference to be relative to the location that input.tex is included from. Looking at the example in the original post, I want a reference that will point to subsec:one:two when input.tex is included within sec:one, but will point to subsec:two:two when input.tex is included in sec:two. I'd like it to point to the :two subsection of whichever section input.tex is placed in.
    – Cameron L
    Commented Jul 1, 2022 at 20:05

2 Answers 2

0

I've been trying to figure out what you want. I'm still a bit uncertain.

I do have concerns. But I'll raise those at the end of this answer or rather start of a deeper conversation. I give the alternative of a deeper conversation because perhaps I missed the point.

Here's a compiled example:

enter image description here

which was created with the following code:

%% --------------------------------------------------
\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}
    
        

The basic idea is to provide a wrapper around the \input{...} that enables you to track the labels. There are several ways you can do this. You could just do this brute force by defining a collection of macros to do the job for you. I opted to use keys to control what I'm doing. Also long as you have the appropriate code in the input file, this should be fairly flexible. Using the same code, you can nevertheless interact with it as though it permitted different label/refs whenever/wherever it's encountered in the text (well, actually my code accomplishes that).

One of the problems that you're encountering with your approach is expandability issues which the manual to xstring does warn about as a potential issue. I'm not an expert in that domain. So, I just left the xstring package and went my own way here.

Concerns and quandaries

My quandary is the very need to re-adjust the ref/label per subsection. From my perspective, all that should matter is the first time you introduce the additional text.

My first concern: While repeating the text might be OK, to refer to the same text multiple times but to different presentation points in the document risks potentially confusing the reader. The reader could be confused thinking there must be something, perhaps subtle, changed that warrants a different label/reference. Why not just say, "On page 5 we first introduced the following idea, which we repeat here for ease of reference"?

My second concern: Anything of substantial length will get repetitive and either annoy or bore the reader. They'll stop paying close attention to what you're writing because you repeat yourself too much. A short snippet, like an equation that warrants reminding the reader about (even though it's been introduced previous) would be fine. But as I mentioned above, it seems it would be more suitable to retain the original label.

2
  • 1
    I will give your methods a try when I have some time, but for now, to address your concerns: The labels don't need to be dynamic. The labels and document structure will be static, defined in the main file. I just want the input files to contain references that "redirect" to different labels, depending on where the file is included. Each section is meant to be the complete, self-contained documentation for a given piece of equipment, so repetition is what I want. This won't be a document you read start-to-finish, but rather one where you refer to one section/piece of equipment at a time.
    – Cameron L
    Commented Jul 6, 2022 at 15:28
  • @CameronL That's actually very helpful feedback. I think I understand better now. I'm going to think about my code some more. Given this new information, there is probably a more efficient way of doing things. Particularly now that I understand your document structure a bit more and understand why repetition of even a sizeable amount makes sense...
    – A.Ellett
    Commented Jul 6, 2022 at 16:24
0

Assuming that you really only want the current subsection, something like this should work:

\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}
2
  • There will be other text in input.tex, not only the reference. I've edited the example accordingly.
    – Cameron L
    Commented Jun 30, 2022 at 22:23
  • Also, what I'm going for isn't necessarily the current subsection, but to another subsection within the same section. So bringing in input.tex in subsec:one:one should give a ref to subsec:one:two (the :two subsection within the same parent sec:one section). But bringing that same input.tex into subsec:two:one should give a ref to subsec:two:two (the :two subsection as before, but within the current parent sec:two section).
    – Cameron L
    Commented Jun 30, 2022 at 22:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .