1

I am writing a document using KOMAscript's scrreprt class, and I am writing a custom macro (\xref) to format text used for cross-references.

This macro takes the label name as an argument: \xref{mylabel}

I want to generate a different text depending on whether the label refers to a chapter/section/subsection (numbered by default) or to a subsubsection/paragraph (unnumbered by default).

How can I check this? Any of the following two would do:

  1. Check if the label refers to a chapter/section/subsection (or the opposite: Check if the label refers to a subsubsection/paragraph)
  2. Check if the label refers to a numbered item
14
  • 2
    Package zref is a good friend, see for example my answer to this question here: tex.stackexchange.com/questions/312060/…
    – user31729
    Feb 1, 2017 at 12:38
  • 3
    You can use cleveref as well
    – user31729
    Feb 1, 2017 at 12:44
  • 1
    Well, what do you think scrreport makes use of in the final end? ;-) Using no extra packages, this you have to do redefinitions in the \label - \ref system. This requires some LaTeX skills. I don't see the point to reinvent the wheel.
    – user31729
    Feb 1, 2017 at 12:47
  • 1
    @Schweinebacke: But that's not expandable (as far as I can remember), which is necessary, to make it working in checks... and it is in an extra package ;-)
    – user31729
    Feb 1, 2017 at 12:52
  • 1
    @Grodiguez: LaTeX itself does not provide a type of element for labels. So you either need to use an additional package or you have to extend the label mechanism of LaTeX similar to such existing packages. I would recommend to use an existing package. Feb 1, 2017 at 12:55

1 Answer 1

5

See the update for referring to unnumbered/numbered structure unit and checking at the end.

Without using any extra packages, only \renewcommand, \let, \pdfstrcmp etc. are used and writing a \@namedef to the .aux file.

It requires two runs (which are needed anyway, since we're dealing with labels!)

Use \extractlabeltype{labelname} and \checklabeltype with true/false branch.

It assumes that no other package is involving with \label and \ref, i.e. no hyperref or cleveref is supported.

\documentclass{book}


\makeatletter
\let\latex@@refstepcounter\refstepcounter
\let\latex@@label\label%


\renewcommand{\refstepcounter}[1]{%
  \gdef\lastrefsteppedcounter{#1}%
  \latex@@refstepcounter{#1}%
}

\renewcommand{\label}[1]{%
  \immediate\write\@auxout{\string\global\string\@namedef{label#1}{\lastrefsteppedcounter}}
   \latex@@label{#1}%
}

\newcommand{\extractlabeltype}[1]{%
  \@nameuse{label#1}%
}

\makeatother

\newcommand{\checklabeltype}[4]{%
\ifnum0=\pdfstrcmp{\extractlabeltype{#1}}{#2}
#3%
\else
#4%
\fi
}


\begin{document}



\chapter{Foo} \label{foo}


\section{Foosection}\label{foosection}

\checklabeltype{foosection}{section}{Yes, it is section}{No, it is something different}

\checklabeltype{foo}{section}{Yes, it is section}{No, it is something different}


\end{document}

enter image description here

Update with checking for unnumbered/numbered issues.

Please not that this deliberately depends on the assumption that the anchor name of a unnumbered structure unit has a * in it, so playing around with \theH... macros is no good idea ;-)

\documentclass{book}

\usepackage{xparse}
\usepackage[hyperref,counter]{zref}% Using the counter mechanism behind `nameref`
\usepackage{hyperref}


\makeatletter
\AtBeginDocument{%
  \let\latex@@label\label%

  \renewcommand{\label}[1]{%
    \zref@label{#1}%
    \latex@@label{#1}%
  }
  % Get the underlying counter type
  \newcommand{\extractlabelcounter}[1]{%
    \zref@ifrefundefined{#1}{%
      ???????}{%
      \zref@extract{#1}{counter}%
    }%
  }
  % Get the anchor name for hyperref or nameref -> has a `*` inside if it is unnumbered
  \newcommand{\extractlabelanchor}[1]{%
    \zref@ifrefundefined{#1}{%
      ???????}{%
      \zref@extract{#1}{anchor}%
    }%
  }
}

% Check if there's a `*` inside of the anchor name
\ExplSyntaxOn
\cs_new:Npn \checkifnumbered#1#2#3{%
  \tl_set:Nx \l_tmpa_tl {\extractlabelanchor{#1}}
  \tl_if_in:NnTF \l_tmpa_tl {*} {#2} {#3}
}
\ExplSyntaxOff

\makeatother


\newcommand{\checklabeltype}[4]{%
  \ifnum0=\pdfstrcmp{\extractlabelcounter{#1}}{#2}
  #3%
  \else
  #4%
  \fi
}

\begin{document}
\chapter{Foo} \label{foo}

\section*{An unnumbered section} \label{unnumbered}

\section{Foosection}\label{foosection}

\checklabeltype{foosection}{section}{Yes, it is section}{No, it is something different}

\checklabeltype{foo}{section}{Yes, it is section}{No, it is something different}

\begin{enumerate}
\item First \label{enumfirst}
\item Second \label{enumsecond}
\end{enumerate}

\checklabeltype{enumsecond}{enumi}{It is a numbered item and has the value \ref{enumsecond}}{}

In \nameref{unnumbered} we have an \checkifnumbered{unnumbered}{unnumbered}{numbered} \extractlabelcounter{unnumbered}


In \nameref{foo} we have an \checkifnumbered{foo}{unnumbered}{numbered} \extractlabelcounter{foo} whereas
 \nameref{foosection} is a \checkifnumbered{foosection}{unnumbered}{numbered} \extractlabelcounter{foosection}.


\end{document}

enter image description here

13
  • +1 for a solution that's compatible with the hyperref and cleveref packages. :-)
    – Mico
    Feb 1, 2017 at 13:25
  • @Mico: Is it? I did not check. I doubt that cleveref's \label[...]{...} will like this ;-).
    – user31729
    Feb 1, 2017 at 13:27
  • @Grodriguez: It's a little bit more complicate with zref but more flexible, currently I am not sure that cleveref is the right package for your needs
    – user31729
    Feb 1, 2017 at 13:45
  • 1
    @Grodiguez: That's just because hyperref changes refstepcounter. \nameref is not expandable, by the way
    – user31729
    Feb 1, 2017 at 22:59
  • 1
    @ChristianHupfer Your updated solution works like a charm. This is just what I was looking for.
    – Grodriguez
    Feb 6, 2017 at 11:50

You must log in to answer this question.

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