# Get label target type

I'm looking for a solution to my previous question "Relative chapter references", and find myself struggling with trying to get the target "type" of a label from the label itself.

Allow me to clarify: I want to determine whether a given label points to either a chapter, section, subsection, figure, table, etc.

Ideas? (cuz I'm plain out)

PS: the solution should be compatible with the hyperref package at the very least.

-
Have you looked at the cleveref package? –  cmhughes Nov 5 '11 at 21:07
@cmhughes: I can only imagine \lcnamecref could be of any use... but lack the skill to turn it into something usefull I'm afraid :S... could you provide an example? –  mpr Nov 5 '11 at 21:28

\documentclass{article}
\usepackage[ngerman]{babel}
\usepackage{hyperref}

\makeatletter

% Helper macro to extract the type (section,subsection...) or the type name
% out of the label reference. Works with hyperref only.
% Argument #1 is a macro of form \def\...#1...\@nil{...}
% Argument #2 is the label reference, e.g. "sect:test"
\newcommand*\@myautoref[2]{% \HyPsd@@@autoref from hyperref, modified
\expandafter\ifx\csname r@#2\endcsname\relax
??%
\else
\expandafter\expandafter\expandafter\@@myautoref
\csname r@#2\endcsname{}{}{}{}\@nil#1\@nil
\fi
}
\def\@@myautoref#1#2#3#4#5\@nil#6\@nil{% \HyPsd@autorefname, modified
#6#4.\@nil}% Argument #4 = type and number, e.g. "section.1" or "subsection.1.2"

% \myreftype results in the type name, e.g. "section" or "figure".
% The starred variant will remove a star, if existent, i.e. "section*" will become "section"
\newcommand\myreftype{%
\@ifstar
{\@myautoref\@@myreftype}%
{\@myautoref\@myreftype}}
\def\@myreftype#1.#2\@nil{#1}
\def\@@myreftype#1.#2\@nil{\@@@myreftype#1*\@nil}
\def\@@@myreftype#1*#2\@nil{#1}

% \myautorefname results in the type prose name (plus space character),
% e.g. "section" in English or "Abschnitt" in German
% (like \autoref, but without number).
% \HyPsd@@autorefname is defined in the hyperref package.
\newcommand*\myautorefname[1]{\@myautoref\HyPsd@@autorefname{#1}}

% An alternative version of \myautorefname without space at the end.
% Since the \space is hard coded inside \HyPsd@@autorefname we use our
% own version called \@myautorefname instead.
% Furthermore we offer a starred variant which will work with labels to
% \section* etc., too.
\renewcommand*\myautorefname{%
\@ifstar
{\@myautoref\@@myautorefname}%
{\@myautoref\@myautorefname}}
\def\@myautorefname#1.#2\@nil{% = \HyPsd@@autorefname without \space
\ltx@IfUndefined{#1autorefname}%
{\ltx@IfUndefined{#1name}%
{}%
{\csname#1name\endcsname}}%
{\csname#1autorefname\endcsname}}
\def\@@myautorefname#1.#2\@nil{%
\expandafter\@myautorefname\@@@myreftype#1*\@nil.\@nil}

\makeatother

\begin{document}

\myreftype{section:one}
\myreftype{subsection:one}
\myreftype{figure:one}
\myreftype{section:two}

\myreftype*{section:one}
\myreftype*{subsection:one}
\myreftype*{figure:one}
\myreftype*{section:two}

\myautorefname{section:one}
\myautorefname{subsection:one}
\myautorefname{figure:one}
\myautorefname{section:two}

\myautorefname*{section:one}
\myautorefname*{subsection:one}
\myautorefname*{figure:one}
\myautorefname*{section:two}

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

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

\begin{figure}
\caption{Figure One}
\label{figure:one}
\end{figure}

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

\end{document}


The code above is an extract of a solution I once wrote for a German LaTeX forum, see: http://www.mrunix.de/forums/showthread.php?t=71566

Please note that this one uses the facilities of hyperref alone. I'm not familiar with packages like varioref or cleverref, so there may be a better solution using one of those packages.

-
This works like a charm! One issue though, it seems as if \myautorefname always leaves a space after itself... is there any way of avoiding this? –  mpr Nov 6 '11 at 8:09
Do you need \myautorefname at all? I just put it in as further example of the usage of \@myautoref. However, the extra space is hard coded as \space inside \HyPsd@@autorefname. If you don't want it you can either copy the code of \HyPsd@@autorefname, save it as \@myautorefname, remove the \space and use this instead, or you can build a wrapper macro which operates inside a group and redefines \space to \relax. I'll add the first approach to my answer right now... –  Axel Sommerfeldt Nov 6 '11 at 8:29
I'm sorry, but your code fails to recognize starred versions of the command (I get section* if I call \myreftype but nothing if I call \myautorefname). Could it be possible to "ignore" the "starrification" of commands and have section* report as section? –  mpr Nov 6 '11 at 15:55
The section* comes from the hyperref package so nothing can be done about this without patching the hyperref package itself. (I don't know why it puts section* into the AUX file but surely there is a reason for it...) If you want to \autoref and \myautorefname work with section* too, you could add the code line \expandafter\def\csname section*autorefname\endcsname{\sectionautorefname} to your document preamble. –  Axel Sommerfeldt Nov 6 '11 at 16:36
I'm actually more interested in getting \myreftype to work properly since I define counters based on the return value of it. Is it not possible to remove an "optional" star from the end of a string or something like it? –  mpr Nov 6 '11 at 16:59