2

I inserted a number of cross-references to different parts of my book. Currently, I simply do so by calling a self-defined macro:

\newcommand\secref[1]{See \ref{#1}, \nameref{#1}.}

This will print a reference such as the following:

See § 3:III.C.2.a), History and Institutions

Thus, the reference to the number, printed by \ref, includes chapter number, section number, subsection number, subsubsection number and paragraph number. Note that I defined my own numbering scheme using alnumsec.

What I want to achieve now is to make \secref aware of its relative position with regards to the label that is being referenced. If the \secref macro for the "History and Institutions" paragraph is called in chapter "§ 3", for instance, the \ref or a replacement command should only print "III.C.2.a)". If the \secref macro is called in chapter "§ 3", section "III", it should only print "C.2.a)", and so on.

But if the macro is called in, let's say, section "III" of chapter "§ 4", it should print "3: III.C.2.a)" In effect, I want to re-create a behaviour that can be found in Microsoft Word, where a cross-reference to a numbered paragraph will only print as much information as is necessary to make the reference unambiguous in the current context.

So unless a chapter,section,etc. number is provided, the reader can assume that the reference is a reference to different section,subsection,etc in the same chapter,section,etc.

Based on @JohnKormylo's comment below and his answer to this question, I have prepared a MWE that tries to achieve what I want by using a custom \secrefnumber macro that parses the content of \getrefnumber, but I am still stuck because compiling the MWE will result in an error "Missing { inserted." (As regards the approach in the MWE: I am aware that the \if\thechapter\temptask will always yield a false because the \temptask does not include the colon; I was going to get to that once the MWE is working).

\documentclass{book}

\usepackage{xstring}
\usepackage{alnumsec}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[hidelinks]{hyperref}

\addto\captionsenglish{%
\renewcommand\chaptername{}}

\alnumsectionlevels{1}{chapter,section} 
\otherseparators{2}
\alnumsecstyle{aR}
\surroundarabic[][]{§ }{:}
\surroundRoman{}{.}

\makeatletter

\newcommand\secref[1]{\secrefnumber{#1}, \nameref{#1}.}

\newcommand{\secrefnumber}[1]{% #1 = label name for subtasks
\@ifundefined{r@#1}{??}{%
\begingroup%
  \edef\temp{\expandafter\detokenize\getrefnumber{#1}}%
  \StrCut{\temp}{:}\temptask\tempsub%
  \edef\templink{\getrefbykeydefault{#1}{anchor}{}}%
  \if\thechapter\temptask%
    \hyperlink{\templink}{\tempsub)}%
  \else%
    \hyperlink{\templink}{\temptask\,\tempsub)}%
  \fi
\endgroup%
}}

\makeatother

\begin{document}

\chapter{My Very First Chapter}

\section{Introduction}
\label{sec:introduction}

\section{Once Upon a Time}

I am referencing \secref{sec:introduction}

\chapter{The Second Chapter}

I am referencing \secref{sec:introduction} again.

\end{document}
9
  • 1
    \ref, \nameref and \pageref are formatted (mostly) when the label is created, not when used. So one would need to store all of the chapter, section etc. numbers separately. This can be cone, but not using standard \labels. Commented May 9, 2015 at 5:21
  • That wouldn't be a problem. I can easily replace \label by any self-defined command.
    – jjbornheim
    Commented May 9, 2015 at 10:21
  • 1
    A test MWE would help. Some document classes and packages rename the counters. Commented May 9, 2015 at 13:47
  • 1
    Actually, using xstring it is possible to parse a \ref after all. See tex.stackexchange.com/questions/208958/… Commented May 9, 2015 at 14:20
  • 1
    I found and fixed the bug. I forgot to check if the label was defined yet. Commented May 9, 2015 at 22:37

2 Answers 2

2

I was having trouble parsing \thechapter, so I created \seclabel to produce a simplified section label.

Evidently the \detokenize step wasn't needed here (I copied it originally from somewhere else).

\documentclass{book}

\usepackage{xstring}
\usepackage{alnumsec}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[hidelinks]{hyperref}

\addto\captionsenglish{%
\renewcommand\chaptername{}}

\alnumsectionlevels{1}{chapter,section} 
\otherseparators{2}
\alnumsecstyle{aR}
\surroundarabic[][]{§ }{:}
\surroundRoman{}{.}

\newcommand\secref[1]{\secrefnumber{#1}, \nameref{#1}.}

\makeatletter
\newcommand{\seclabel}[1]{% #1 = label name
  \protected@edef\@currentlabel{\arabic{chapter}.\Roman{section}}%
  \label{#1}%
}

\newcommand{\secrefnumber}[1]{% #1 = label name
\@ifundefined{r@#1}{??}{%
\begingroup% use local definitions
  \edef\temp{\getrefnumber{#1}}% string containing \ref
  \StrCut{\temp}{.}\tempchap\temp% separate chapter
  \edef\templink{\getrefbykeydefault{#1}{anchor}{}}% \hyperlink anchor
  \if\arabic{chapter}\tempchap% same chapter
    \hyperlink{\templink}{\temp}%
  \else%
    \hyperlink{\templink}{§ \tempchap:\temp}%
  \fi
\endgroup%
}}

\makeatother

\begin{document}

\chapter{My Very First Chapter}

\section{Introduction}
\seclabel{sec:introduction}

\section{Once Upon a Time}

I am referencing \secref{sec:introduction}

\chapter{The Second Chapter}

I am referencing \secref{sec:introduction} again.

\end{document}
1
  • This is brilliant. Cheers! I scaled your solution all the way to the subparagraph level. Yours is definitely the answer, but I am going to post my modification of your work just so people can see how to scale it all the way down.
    – jjbornheim
    Commented May 11, 2015 at 11:06
0

As I said, John Kormylo answered the question. I am going to include my modification of his answer that applies a scheme all the way down to the sub-paragraph level for reference's sake. Two things I noticed: the etoolbox test works more reliably, which is why I used that rather than a simple \if; second, xstring seems to do something funky to the strings, so I had to xstringify all current section values.

\documentclass{book}

\usepackage{xstring}
\usepackage{alnumsec}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}
\usepackage{varioref}
\usepackage{csquotes}
\usepackage[hidelinks]{hyperref}

\addto\captionsenglish{%
\renewcommand\chaptername{}}

\makeatletter

\alnumsectionlevels{1}{chapter,section,subsection,subsubsection,paragraph,subparagraph} 
\otherseparators{2}
\alnumsecstyle{aRLald}
\surroundarabic[][.]{§ }{:}
\surroundLetter{}{.}
\surroundRoman{}{.}
\surroundletter{}{)}
\surrounddoubleletter{(}{)}
\surroundgreek{(}{)}

\newcommand\secref[1]{\secrefnumber{#1}\thinspace\enquote{\nameref{#1}}\thinspace\vpageref{#1}}

\@addtoreset{section}{chapter}

\@addtoreset{subsection}{chapter}
\@addtoreset{subsection}{section}

\@addtoreset{subsubsection}{chapter}
\@addtoreset{subsubsection}{section}
\@addtoreset{subsubsection}{subsection}

\@addtoreset{paragraph}{chapter}
\@addtoreset{paragraph}{section}
\@addtoreset{paragraph}{subsection}
\@addtoreset{paragraph}{subsubsection}

\@addtoreset{subparagraph}{chapter}
\@addtoreset{subparagraph}{section}
\@addtoreset{subparagraph}{subsection}
\@addtoreset{subparagraph}{subsubsection}
\@addtoreset{subparagraph}{paragraph}

\newcommand{\seclabel}[1]{%
  \protected@edef\@currentlabel{%
    \ifnumgreater{\value{chapter}}{0}{\arabic{chapter}}{}%
    \ifnumgreater{\value{section}}{0}{.\Roman{section}}{}%
    \ifnumgreater{\value{subsection}}{0}{.\Alph{subsection}}{}%
    \ifnumgreater{\value{subsubsection}}{0}{.\arabic{subsubsection}}{}%
    \ifnumgreater{\value{paragraph}}{0}{.\alph{paragraph}}{}%
    \ifnumgreater{\value{subparagraph}}{0}{.\alph{subparagraph}\alph{subparagraph}}{}%
   }%
  \label{#1}%
}

\newcommand{\secref@finaldelim}{:}
\newcommand{\secref@chapname}{§\thinspace }
\newcommand{\secref@secname}{section }
\newcommand{\secref@subname}{subsection }
\newcommand{\secref@subsname}{sub-subsection }
\newcommand{\secref@parname}{paragraph }
\newcommand{\secref@subparname}{subparagraph }

\newcommand{\secrefnumber}[1]{%
\@ifundefined{r@#1}{??}{%
\begingroup% use local definitions
  \edef\secref@name{\relax}%
  \edef\secref@text{\relax}%
  \edef\secref@rest{\getrefnumber{#1}}% string containing \ref
  \StrCut{\arabic{chapter}}{.}\secref@currchap\secref@trash% xstringify chapter number
  \StrCut{\Roman{section}}{.}\secref@currsec\secref@trash% xstringify section number
  \StrCut{\Alph{subsection}}{.}\secref@currsub\secref@trash% xstringify subsection number
  \StrCut{\arabic{subsubsection}}{.}\secref@currsubs\secref@trash% xstringify sub-subsection number
  \StrCut{\alph{paragraph}}{.}\secref@currpar\secref@trash% xstringify paragraph number
  \StrCut{\alph{subparagraph}\alph{subparagraph}}{.}\secref@currsubpar\secref@trash% xstringify subparagraph number
  \StrCut{\secref@rest}{.}\secref@chap\secref@rest% extract chapter number
  \StrCut{\secref@rest}{.}\secref@sec\secref@rest% extract section number
  \StrCut{\secref@rest}{.}\secref@sub\secref@rest% extract subsection number
  \StrCut{\secref@rest}{.}\secref@subs\secref@rest% extract subsubsection number
  \StrCut{\secref@rest}{.}\secref@par\secref@rest% extract parapraph number
  \StrCut{\secref@rest}{.}\secref@subpar\secref@rest% extract subparagraph number
  \edef\secref@restlink{\getrefbykeydefault{#1}{anchor}{}}% \hyperlink anchor
  \ifdefstrequal{\secref@currchap}{\secref@chap}% target in same chapter?
    {\ifdefstrequal{\secref@currsec}{\secref@sec}% target in same chapter (+); target in same section?
      {\ifdefstrequal{\secref@currsub}{\secref@sub}% target in same section (+), target in same subsection?
         {\ifdefstrequal{\secref@currsubs}{\secref@subs}% target in same subsection (+), target in same subsubsection?
           {\ifdefstrequal{\secref@currpar}{\secref@par}%target in same subsubsection (+), target in same paragraph?
             {\edef\secref@text{\secref@subpar}% target in same paragraph (+)
              \let\secref@name\secref@subparname}%
             {\edef\secref@text{\secref@par% target in same paragraph ()-)
                \ifdefvoid{\secref@subpar}%
                  {}%
                  {.\secref@subpar}}%
               \let\secref@name\secref@parname}% 
            }%
           {\edef\secref@text{\secref@subs% target in same subsubsection (-)
              \ifdefvoid{\secref@par}%
                {}%
                {.\secref@par%
                 \ifdefvoid{\secref@subpar}%
                   {}%
                   {.\secref@subpar}}%
                 }%  
             \let\secref@name\secref@subsname}% 
          }% 
         {\edef\secref@text{% target in same subsection (-)
          \secref@sub%
          \ifdefvoid{\secref@subs}%
            {}%
            {.\secref@subs%
             \ifdefvoid{\secref@par}%
              {}%
              {.\secref@par%
               \ifdefvoid{\secref@subpar}%
                 {}%
                 {.\secref@subpar}}%
               }%
             }%
           \let\secref@name\secref@subname}%
        }%
      {\edef\secref@text{% target in same section (-)
       \secref@sec%
       \ifdefvoid{\secref@sub}%
         {}%
         {.\secref@sub%
          \ifdefvoid{\secref@subs}%
           {}%
           {.\secref@subs%
             \ifdefvoid{\secref@par}%
              {}%
              {.\secref@par%
               \ifdefvoid{\secref@subpar}%
                 {}%
                 {.\secref@subpar}}%
               }%
             }%
           }%
         \let\secref@name\secref@secname}%
       }%
    {\edef\secref@text{% target in different chapter (+)
      \secref@chap%
      \ifdefvoid{\secref@sec}%
        {}%
        {:\secref@sec%
         \ifdefvoid{\secref@sub}%
           {}%
           {.\secref@sub%
            \ifdefvoid{\secref@subs}%
              {}%
              {.\secref@subs%
                \ifdefvoid{\secref@par}%
                  {}%
                  {.\secref@par%
                   \ifdefvoid{\secref@subpar}%
                     {}%
                     {.\secref@subpar}}%
                 }%
               }%
             }%
           }%
         \let\secref@name\secref@chapname}%
\hyperlink{\secref@restlink}{\secref@name\secref@text}%
\endgroup%
}%
\secref@finaldelim\relax}

\makeatother

\begin{document}

\chapter{My Very First Chapter}


\section{Introduction}
\seclabel{sec:introduction}

\subsection{First Subsection of the Introduction}
\seclabel{sec:first_sub_section}

I am referencing \secref{sec:second_chapter}.

\subsubsection{First Sub-Subsection}

\paragraph{First Paragraph}
\seclabel{sec:first_paragraph}

\subparagraph{First Subparagraph}
\seclabel{sec:first_subparagraph}

\subparagraph{Second Subparagraph}

This is a reference to \secref{sec:first_subparagraph}.

\paragraph{Second Paragraph}

This is a reference to \secref{sec:first_paragraph}. And here is one to \secref{sec:first_subparagraph}.

\subsubsection{Second Sub-Subsection}

This is another reference to \secref{sec:first_subparagraph}.

\subsection{Second Subsection of the Introduction}

I am referencing \secref{sec:first_sub_section}.

\section{Once Upon a Time}

I am referencing \secref{sec:introduction}. Now I am referencing \secref{sec:first_sub_section} again.

\chapter{The Second Chapter}
\seclabel{sec:second_chapter}

I am referencing \secref{sec:first_sub_section} again.

\end{document}

You must log in to answer this question.

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