Store URLs in a macro without replaceing # and %

You asked,

"How can I store a URL in a macro if the URL has a # and/or a % in it?"

The \urldef directive of the url package lets you create precisely such macros. E.g.,

\urldef{\myURL}\url{https://books.google.com/books?id=4tFFDwAAQBAJ&pg=PT233&dq=history+of+trigonometry&hl=en&newbks=1&newbks_redir=0&sa=X&ved=2ahUKEwjIzcj0-tnqAhXwFjQIHZ6XDLUQ6AEwAnoECAQQAg#v=onepage&q&f=false}

Note the syntax: \urldef{<macroname>}\url{<URLstring>}. Observe taht \url{<URLstring>} must not be enclosed in curly braces.

\myUrl may be used in the argument of \footnote directives.


hyperref's \hyper@normalise comes in extremely handy here. It can be used to sanitise the argument of a macro and allow it to accept special characters without escaping. (I think I first learned about \hyper@normalise from Michael Ummels' answer to Getting those %#!^& signs in the footnote!)

Just use it to define a new macro like \newcommand*{\csdefurl}[1]{\hyper@normalise{\csdef{#1}}}. (Note that the argument that is going to be "normalised" is not explicitly part of the definition. \newcommand*{\csdefurl}[2]{\hyper@normalise{\csdef{#1}}{#2}} would not work because then the argument is read with the unnormalised catcode setup.)

\documentclass{article}
\usepackage{etoolbox}
\usepackage{hyperref}
\usepackage{tikz}

\makeatletter
\newcommand*{\csdefurl}[1]{\hyper@normalise{\csdef{#1}}}
\makeatother

\csdef{url Title 1}{The Google}
\csdefurl{url Link 1}{http://www.google.com}

\csdef{url Title 2}{TeX.SE}
\csdefurl{url Link 2}{http://tex.stackexchange.com}

\csdef{url Title 3}{Algebra and Trigonometry:~History of Trigonometry}
\csdefurl{url Link 3}{https://example.com/~test/a%20and%20b.html#anchor}

\def\MaxNUmberOfURLs{5}
\newcommand{\DisplayURLs}{%
    \textbf{List of URLs}
    \foreach \xCount in {1,...,\MaxNUmberOfURLs} {%
        \ifcsdef{url Title \xCount}{%
            \par\xCount:
            \href{\csuse{url Link \xCount}}{\csuse{url Title \xCount}}
        }{}%
    }%
}

\begin{document}
\DisplayURLs
\end{document}

Screenshot of the output. The third item reads "Algebra and Trigonometry: History of Trigonometry" and the little pop-up the PDF viewer shows on hover displays "https://example.com/~test/a%20and%20b.html#anchor"


Some more testing reveals that

\makeatletter
\newcommand*{\csdefurl@i}{}
\newrobustcmd*{\csdefurl}[1]{%
  \def\csdefurl@i{\csdef{#1}}%
  \hyper@normalise\csdefurl@i}
\makeatother

might be safer.

Compare this definition to the one above in

\documentclass{article}
\usepackage{etoolbox}
\usepackage{hyperref}
\usepackage{tikz}

\makeatletter
\newcommand*{\csdefurl@i}{}
\newrobustcmd*{\csdefurl}[1]{%
  \def\csdefurl@i{\csdef{#1}}%
  \hyper@normalise\csdefurl@i}
\makeatother

\csdef{ürl Title 1}{The Google}
\csdefurl{ürl Link 1}{http://www.google.com}

\csdef{ürl Title 2}{TeX.SE}
\csdefurl{ürl Link 2}{http://tex.stackexchange.com}

\csdef{ürl Title 3}{Algebra and Trigonometry:~History of Trigonometry}
\csdefurl{ürl Link 3}{https://example.com/~test/a%20and%20b.html#anchor}

\def\MaxNUmberOfURLs{5}
\newcommand{\DisplayURLs}{%
    \textbf{List of URLs}
    \foreach \xCount in {1,...,\MaxNUmberOfURLs} {%
        \ifcsdef{ürl Title \xCount}{%
            \par\xCount:
            \href{\csuse{ürl Link \xCount}}{\csuse{ürl Title \xCount}}
        }{}%
    }%
}

\begin{document}
\DisplayURLs
\end{document}

where we have the non-ASCII ürl instead of url.

Tags:

Hyperref

Urls