\ nameref utilizzando testo "non espanso"?

Nov 03 2020

Supponiamo che io definisca un comando personalizzato \exercisecome segue.

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

Ora, nel seguente esempio, voglio usare \namerefdal hyperrefpacchetto.

\exercise\label{ex:first}
foo

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

\exercise\label{ex:third}
bar

Questo produce "vedi esercizio 2" invece di "vedi esercizio 1". Sembra che venga utilizzato il testo "non espanso", che si espande nel valore corrente del contatore. Come posso assicurarmi che \nameref{ex:first}produca "Esercizio 1"?

(Ovviamente, potrei semplicemente usare Exercise~\ref{ex:first}, ma questo è più soggetto a errori. E, in futuro, potrei voler sostituire "esercizio" con "problema" senza dover trovare e sostituire tutte le occorrenze nel mio documento.)


Esempio completo:

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

Risposte

1 egreg Nov 03 2020 at 16:08

In effetti, è necessario passare l'espansione di \theexercise, perché hyperrefnon lo fa per il titolo.

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

Questo è il contenuto (abbreviato) del .auxfile:

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

Era

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

con il tuo codice.

Nota. Perché \unexpanded{Exercise}? Nel caso particolare non è ovviamente necessario, ma lo sarebbe per il tedesco “Übung”.


Potresti usare cleverefinvece.

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

L'output è lo stesso in entrambi i casi.

Possiamo evitare il \edef\x{\endgrouptrucco? Sì, naturalmente.

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

Nota che cleverefnon è necessario, se preferisci rimuovi le chiamate pertinenti \nameref.