TransWikia.com

nameref using 'unexpanded' text?

TeX - LaTeX Asked by Gooz on July 20, 2021

Suppose I define a custom command exercise as follows.

newcounter{exercise}
newcommandexercise{%
    refstepcounter{exercise}%
    section*{Exercise theexercise}%
}

Now, in the following example, I want to use nameref from the hyperref package.

exerciselabel{ex:first}
foo

exerciselabel{ex:second}
see nameref{ex:first}

exerciselabel{ex:third}
bar

This produces "see Exercise 2" instead of "see Exercise 1". It seems like the ‘unexpanded’ text is used, expanding into the current counter value. How can I make sure that nameref{ex:first} produces "Exercise 1"?

(Of course, I could just use Exercise~ref{ex:first}, but this is more error-prone. And, in the future, I may want to replace "exercise" by "problem" without having to find and replace all occurences in my document.)


Full example:

documentclass{article}

usepackage{hyperref}

newcounter{exercise}
newcommandexercise{%
    refstepcounter{exercise}%
    section*{Exercise theexercise}%
}

begin{document}

exerciselabel{ex:first}
foo

exerciselabel{ex:second}
see nameref{ex:first}

exerciselabel{ex:third}
bar

end{document}

One Answer

Indeed, you need to pass the expansion of theexercise, because hyperref doesn't do it to the title.

documentclass{article}
usepackage{hyperref}

newcounter{exercise}
newcommandexercise{%
  par % just in case
  refstepcounter{exercise}%
  begingroupedefx{endgroup
    noexpandsection*{unexpanded{Exercise} theexercise}%
  }x
}

begin{document}

exerciselabel{ex:first}
foo

exerciselabel{ex:second}
see nameref{ex:first}

exerciselabel{ex:third}
bar

end{document}

This is the (abridged) contents of the .aux file:

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

It was

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

with your code.

Note. Why unexpanded{Exercise}? In the particular case it is obviously unnecessary, but it would be for the German “Übung”.


You might use cleveref instead.

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

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

begin{document}

exerciselabel{ex:first}
foo

exerciselabel{ex:second}
see cref{ex:first}

exerciselabel{ex:third}
bar

end{document}

The output is the same in both cases.

enter image description here

Can we avoid the edefx{endgroup trick? Yes, of course.

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}

exerciselabel{ex:first}
foo

exerciselabel{ex:second}
see cref{ex:first} or nameref{ex:first}

exerciselabel{ex:third}
bar

end{document}

Note that cleveref is not necessary, just remove the relevant calls if you prefer nameref.

Correct answer by egreg on July 20, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP