\ nameref en utilisant du texte 'non développé'?

Nov 03 2020

Supposons que je définis une commande personnalisée \exercisecomme suit.

\newcounter{exercise}
\newcommand\exercise{%
    \refstepcounter{exercise}%
    \section*{Exercise \theexercise}%
}

Maintenant, dans l'exemple suivant, je souhaite utiliser à \namerefpartir du hyperrefpackage.

\exercise\label{ex:first}
foo

\exercise\label{ex:second}
see \nameref{ex:first}

\exercise\label{ex:third}
bar

Cela produit "voir exercice 2" au lieu de "voir exercice 1". Il semble que le texte «non développé» soit utilisé, se développant dans la valeur actuelle du compteur. Comment puis-je m'assurer que \nameref{ex:first}"Exercice 1" produit?

(Bien sûr, je pourrais simplement utiliser Exercise~\ref{ex:first}, mais c'est plus sujet aux erreurs. Et, à l'avenir, je pourrais vouloir remplacer «exercice» par «problème» sans avoir à trouver et remplacer toutes les occurrences dans mon document.)


Exemple complet:

\documentclass{article}

\usepackage{hyperref}

\newcounter{exercise}
\newcommand\exercise{%
    \refstepcounter{exercise}%
    \section*{Exercise \theexercise}%
}

\begin{document}

\exercise\label{ex:first}
foo

\exercise\label{ex:second}
see \nameref{ex:first}

\exercise\label{ex:third}
bar

\end{document}

Réponses

1 egreg Nov 03 2020 at 16:08

En effet, vous devez passer l'expansion de \theexercise, car hyperrefne le fait pas pour le titre.

\documentclass{article}
\usepackage{hyperref}

\newcounter{exercise}
\newcommand\exercise{%
  \par % just in case
  \refstepcounter{exercise}%
  \begingroup\edef\x{\endgroup
    \noexpand\section*{\unexpanded{Exercise} \theexercise}%
  }\x
}

\begin{document}

\exercise\label{ex:first}
foo

\exercise\label{ex:second}
see \nameref{ex:first}

\exercise\label{ex:third}
bar

\end{document}

Voici le contenu (abrégé) du .auxfichier:

\newlabel{ex:first}{{1}{1}{Exercise 1}{section*.1}{}}
\newlabel{ex:second}{{2}{1}{Exercise 2}{section*.2}{}}
\newlabel{ex:third}{{3}{1}{Exercise 3}{section*.3}{}}

C'était

\newlabel{ex:first}{{1}{1}{Exercise \theexercise }{section*.1}{}}
\newlabel{ex:second}{{2}{1}{Exercise \theexercise }{section*.2}{}}
\newlabel{ex:third}{{3}{1}{Exercise \theexercise }{section*.3}{}}

avec votre code.

Remarque. Pourquoi \unexpanded{Exercise}? Dans le cas particulier, ce n'est évidemment pas nécessaire, mais ce serait pour le «Übung» allemand.


Vous pourriez utiliser à la cleverefplace.

\documentclass{article}
\usepackage{hyperref}
\usepackage[nameinlink]{cleveref}

\newcounter{exercise}
\newcommand\exercise{%
  \par % just in case
  \refstepcounter{exercise}%
  \section*{Exercise \theexercise}
}
\crefname{exercise}{Exercise}{Exercises}

\begin{document}

\exercise\label{ex:first}
foo

\exercise\label{ex:second}
see \cref{ex:first}

\exercise\label{ex:third}
bar

\end{document}

La sortie est la même dans les deux cas.

Pouvons-nous éviter le \edef\x{\endgrouptruc? Oui bien sûr.

\documentclass{article}
%\usepackage{xparse} % not needed for LaTeX 2020-10-01 or later
\usepackage{hyperref}
\usepackage[nameinlink]{cleveref}

\ExplSyntaxOn
\NewDocumentCommand{\exercise}{}
 {
  \gooz_exercise:ne { \exercisename } { \theexercise }
 }
\cs_new_protected:Nn \gooz_exercise:nn
 {
  \par % just in case
  \refstepcounter{exercise}
  \section*{#1~#2}
 }
\cs_generate_variant:Nn \gooz_exercise:nn { ne }
\ExplSyntaxOff

\newcommand{\exercisename}{Exercise}
\newcounter{exercise}
\crefname{exercise}{\exercisename}{\exercisename s}

\begin{document}

\exercise\label{ex:first}
foo

\exercise\label{ex:second}
see \cref{ex:first} or \nameref{ex:first}

\exercise\label{ex:third}
bar

\end{document}

Notez que ce cleverefn'est pas nécessaire, supprimez simplement les appels concernés si vous préférez \nameref.