4

Donald Arsenau's url package provides the macro \urldef, which is very handy when one needs to typeset a URL string in a footnote or endnote. For instance,

\documentclass{article}
\usepackage{url}     % for \url and \urldef commands
\usepackage{enotez}  % for \endnote and \printendnotes commands
\setenotez{backref = true}
\usepackage{hyperref}
\hypersetup{colorlinks,urlcolor=blue}

\begin{document} \urldef{\basicurl}\url{https://tex.stackexchange.com/questions} blabla\endnote{\basicurl}

\clearpage \printendnotes \end{document}

generates

Enter image description here

on the endnotes page, where the red numeral 1 is a back-reference to the location in the main document where the \endnote command occurred.

So far, so good. Is there a way to generalize this setup by replacing the hard-coded macro name \basicurl with, say, \csname zz\themycounter\endcsname?

Here, \themycounter is the arabic-numeral expression of the value of a counter variable name named mycounter. (By way of background: The document will eventually hold many endnotes, each with one URL string, and it's not feasible to define a new \basicurl directive before each and every \endnote command. I'm trying to make the argument of \urldef unique, in order to play nice with the enotez package. For more background information, please see this query.)

I naively tried

\documentclass{article}
\newcounter{mycounter}
\usepackage{url}     % for \url and \urldef commands
\usepackage{enotez}  % for \endnote and \printendnotes commands
\setenotez{backref = true}
\usepackage{hyperref}
\hypersetup{colorlinks,urlcolor=blue}

\begin{document} \stepcounter{mycounter} \urldef{\csname zz\themycounter\endcsname}\url{https://tex.stackexchange.com/questions} blabla\endnote{\csname zz\themycounter\endcsname} \clearpage \printendnotes \end{document}

But this generates the following error message:

! Extra \endcsname.
\declare@robustcommand ...e \string #1 \endcsname

l.11 ...url{https://tex.stackexchange.com/questions}

Am I doing something wrong, or can \urldef truly not handle \csname ... \endcsname-type macro commands?


Addendum, posted upon receiving @JairoA.delRio' suggestion to replace

\urldef{\csname zz\themycounter\endcsname}\url{...}

with

\expandafter\urldef\expandafter{\csname zz\themycounter\endcsname}\url{...}

This modification definitely solves the problem mentioned above. However, it leads to another problem, best illustrated by the following, expanded (pun intended) MWE:

\documentclass{article}
\newcounter{mycounter}
\usepackage{url}     % for \url and \urldef commands
\usepackage{enotez}  % for \endnote and \printendnotes commands
\setenotez{backref = true}
\usepackage{hyperref}
\hypersetup{colorlinks,urlcolor=blue}

\begin{document}

\stepcounter{mycounter} \expandafter\urldef\expandafter{\csname zz\themycounter\endcsname}\url{https://tex.stackexchange.com/questions} blabla\endnote{\csname zz\themycounter\endcsname}

\stepcounter{mycounter} \expandafter\urldef\expandafter{\csname zz\themycounter\endcsname}\url{https://www.sciencedirect.com/science/article/abs/pii/S0304405X00000763} more blabla\endnote{\csname zz\themycounter\endcsname}

\clearpage \printendnotes \end{document}

This is basically the same as before -- except for the additional set of \stepcounter{mycounter}, \urldef, and \endnote directives. Unhappily, the endnotes page now consists of the following:

Enter image description here

Oberve that the same URL string is shown twice even though the two instances of \endnote use the equivalent of \zz1 and \zz2, respectively.

Updated question: Is there something else about my code that's not quite right, or have I maybe come across a bug in the enotez package?

Mico
  • 506,678
  • 1
    \expandafter\urldef\expandafter{\csname zz\themycounter\endcsname}\url{https://tex.stackexchange.com/questions}? –  Apr 25 '21 at 07:53
  • @JairoA.delRio - Many thanks for this suggestion! It definitely solves one problem, but another one remains. I will post an addendum to the query to illustrate what happens to the endnotes when this setup is employed twice. – Mico Apr 25 '21 at 08:17
  • It would be better to update the question such that it would appear as if it was written right now (the historical information is in the revision history). (It is probably not a chameleon question.) – Peter Mortensen Apr 25 '21 at 17:45

2 Answers2

5

With \endnote{\csname zz\themycounter\endcsname}, the text stored in the endnote will have \themycounter and so the value current at the time \printendnotes will be used.

You have to build the control sequence name before \endnote starts its job. But there's a catch! There's always a catch, you know…

Due to how enotez processes the token lists it's fed with, \zz2 (resulting from your \urldef, will be treated separately (this is because the thing is stored in the .aux file) as if it were \zz followed by 2.

How to fix? Use Roman numerals instead of Arabic ones.

\documentclass{article}
\usepackage{url}     % for \url and \urldef commands
\usepackage{enotez}  % for \endnote and \printendnotes commands
\usepackage{hyperref}

\setenotez{backref = true} \hypersetup{colorlinks,urlcolor=blue}

\newcounter{mycounter} \renewcommand{\themycounter}{\romannumeral\value{mycounter}}

\begin{document}

\stepcounter{mycounter} \expandafter\urldef\csname zz\themycounter\endcsname \url{https://tex.stackexchange.com/questions}

blabla\expandafter\endnote\expandafter{\csname zz\themycounter\endcsname}

\stepcounter{mycounter}

\expandafter\urldef\csname zz\themycounter\endcsname \url{https://www.sciencedirect.com/science/article/abs/pii/S0304405X00000763}

more blabla\expandafter\endnote\expandafter{\csname zz\themycounter\endcsname}

\clearpage \printendnotes

\end{document}

Why not

\renewcommand{\themycounter}{\roman{mycounter}}

instead of using the primitive \romannumeral? Because some babel modules redefine \roman in a way that would conflict with this job.

enter image description here

We can define a macro for this kind of endnotes.

\documentclass{article}
\usepackage{url}     % for \url and \urldef commands
\usepackage{enotez}  % for \endnote and \printendnotes commands
\usepackage{hyperref}

\setenotez{backref = true} \hypersetup{colorlinks,urlcolor=blue}

\ExplSyntaxOn \NewDocumentCommand{\endnoteurl}{v} { \int_incr:N __mico_endnoteurl_int \exp_args:Nc \urldef { zz \int_to_roman:n { __mico_endnoteurl_int } } \url{#1} \exp_args:Ne \endnote { \exp_not:c { zz \int_to_roman:n { __mico_endnoteurl_int } } } } \int_new:N __mico_endnoteurl_int \ExplSyntaxOff

\begin{document}

blabla\endnoteurl{https://tex.stackexchange.com/questions}

more blabla\endnoteurl{https://www.sciencedirect.com/science/article/abs/pii/S0304405X00000763}

\clearpage \printendnotes

\end{document}

egreg
  • 1,121,712
3

This is an expansion problem. The first issue has been discussed by Jairo A. del Rio in the comments: You need to expand \csname <string>\endcsname before \urldef tries to use it. So

\expandafter\urldef\expandafter{\csname zz\themycounter\endcsname}
  \url{https://tex.stackexchange.com/questions}

works.

This is because \urldef behaves pretty much like \def here. With

\def\csname zz\themycounter\endcsname{Hullo}

you redefine \csname. But with

\expandafter\def\csname zz\themycounter\endcsname{Hullo}

you actually redefine \zz<expansion of \themycounter>.

A similar thing holds for \endnote, but there we additionally need to take into account that \endnote writes the contents of the endnote to an external file (which needs care in terms of expansion).

\endnote tries to write its argument as is without expansion. You'll want \endnote to write \csname zz<expansion of \themycounter>\endcsname to the file, not \csname zz\themycounter\endcsname or anything else (in particular we also don't want \zz1, we need \csname zz1\endcsname).

I gave up trying to figure out the optimal number of expansions here (it's three in this case) and just went for a full \edef expansion with the old \begingroup \edef...{\endgroup} trick (Explanations about \begingroup\edef\x{\endgroup). (This is safe as long as \themycounter is expandable, which you already assume when you say \csname zz\themycounter\endcsname).

Both of these things are probably easiest done with a helper definition.

\documentclass{article}
\usepackage{url}
\usepackage{enotez}
\setenotez{backref = true}
\usepackage{hyperref}
\hypersetup{colorlinks,urlcolor=blue}

\newcounter{mycounter}

\newcommand\zzurldef{\zzurldednr{\themycounter}} \newcommand\zzurldednr[1]{\expandafter\urldef\expandafter{\csname zz#1\endcsname}}

\newcommand\zzendnote{% \begingroup \edef\temp{\endgroup \noexpand\zzendnotenr{\themycounter}}% \temp} \newcommand\zzendnotenr[1]{\endnote{\csname zz#1\endcsname}}

\begin{document} \stepcounter{mycounter} \zzurldef\url{https://tex.stackexchange.com/questions} blabla\zzendnote

\stepcounter{mycounter} \zzurldef\url{https://www.sciencedirect.com/science/article/abs/pii/S0304405X00000763} more blabla\zzendnote

\printendnotes \end{document}

Notes//1. https://tex.stackexchange.com/questions//2. https://www.sciencedirect.com/science/article/abs/pii/S0304405X00000763

moewe
  • 175,683
  • 1
    Many thanks for your answer, which works just fine. In the end, though, I chose to award the check-mark to @egreg's answer, as I find its code to be every so slightly more elegant. – Mico Apr 26 '21 at 19:53