[Tex/LaTex] Getting those %#!^& signs in the footnote!

footnoteshyperrefverbatim

This is basically an expanded version of part of Control command arguments . The original questioner there wants to redefine \href so that all the links end up in foonotes (rather than in the main document) so my suggestion was the old \let\oldcmd=\cmd \def\cmd{reimplement \cmd in some fancy way} trick. Turned out that that didn't solve the problem. But what broke this solution isn't really about the solution, it's about those @&*@%y$#@ characters in URLs and … *sigh* … footnotes.

Not being an expert on hyperref, I appeal to the community to help. (And half an hour gazing at the documentation and source of hyperref has not brought enlightenment either.) I've tried the solutions at Getting percent sign into an URL in a footnote and Is there a reliable footnote command? to no avail (though perhaps I'm doing them wrong … sorry, incorrectly). Also, note that How display the href link in the footnote? is the wrong way around for this: the questioner wants the clickable link in the footnote.

Here's the URL that the questioner presented me with, embedded in a MWE:

\documentclass{article}
\usepackage{hyperref}

\begin{document}
Hello\footnote{\href{http://www.google.com/#sclient=psy&hl=en&site=&source=hp&q=numbers&aq=f&aqi=&aql=&oq=&pbx=1&fp=d5033c56880e0199}{b}} world.

\end{document}

This produces the error:

! Illegal parameter number in definition of \Hy@tempa.
<to be read again> 
                   s
l.9 ...qi=&aql=&oq=&pbx=1&fp=d5033c56880e0199}{b}}
                                                   world.

which makes me think that it is the # that is causing the problem.

Best Answer

The url package (used by hyperref) gives you the \Url@HyperHook hook, which is also used in \urldef (see Getting percent sign into an URL in a footnote). The original URL string is located in \Url@String (expandable) and the already formatted string in \Url@FormatString (not expandable).

This can be used to implement your own \url like macros. The code below then creates the wanted \footnote with an \href. A second macro is required to read the second argument of \href after the URL. This is a little tricky because the rest of the internal code of \url most be jumped over first and then reinserted.

\documentclass{article}

\usepackage{hyperref}

\makeatletter

\def\hreffootnote{%
    %\unskip % maybe required
    \begingroup
    \def\Url@HyperHook ##1\endgroup{%
        \let\Url@HyperHook\relax
        \href@footnote
    }%
    \url
}

\let\realhref\href
\def\href@footnote#1\endgroup#2{%
   \footnote{\expandafter\realhref\expandafter{\Url@String}{#2}}%
   \endgroup\endgroup#1\endgroup%  #1 is some internal `\url` code
}


\begin{document}

Text\hreffootnote{http://foobar.com/~test/%^&*$_##/test}{there} after

Text \href{http://foobar.com/~test/%^&*$_##/test}{there} after

\let\href\hreffootnote
Text \href{http://foobar.com/~test/%^&*$_##/test}{there} after

Hello\hreffootnote{http://www.google.com/#sclient=psy&hl=en&site=&source=hp&q=numbers&aq=f&aqi=&aql=&oq=&pbx=1&fp=d5033c56880e0199}{b} world.


\end{document}

Alternatively a home made solution which reads the first argument verbatim (except { } characters):

\documentclass{article}

\usepackage{hyperref}

\makeatletter

\def\hreffootnote{%
    %\unskip
    \begingroup
    \let\do\@makeother
    \dospecials
    \catcode`\{=1\relax
    \catcode`\}=2\relax
    \href@footnote
}
\def\href@footnote#1{%
    \endgroup
    \href@@footnote{#1}%
}
\let\realhref\href
\def\href@@footnote#1#2{%
    \footnote{\realhref{#1}{#2}}%
}

\begin{document}

Text\hreffootnote{http://foobar.com/~test/%^&*$_##/test}{there} after

Text \href{http://foobar.com/~test/%^&*$_##/test}{there} after

\let\href\hreffootnote
Text \href{http://foobar.com/~test/%^&*$_##/test}{there} after

Hello\hreffootnote{http://www.google.com/#sclient=psy&hl=en&site=&source=hp&q=numbers&aq=f&aqi=&aql=&oq=&pbx=1&fp=d5033c56880e0199}{b} world.

\end{document}

Update 2011-07-27:

I now published a new version of newverbs which provides \collectverb and \Collectverb to collect verbatim arguments easily. For the sake of completeness here again the full solution based on this package. (It is also an answer to Changing href's to footnotes).

\documentclass{article}

\usepackage{hyperref}
\usepackage{newverbs}[2011/07/24]

\let\orighref\href
\renewcommand{\href}{\Collectverb{\hrefii}}
\newcommand\hrefii[2]{\footnote{\orighref{#1}{#2}}}

\usepackage{lipsum}% Dummy text
\begin{document}

\lipsum*[1]\href{http://test.com/%$^£$%^_@~}{Test URL}

% With other argument separators as { }:
\lipsum*[2]\href|http://test.com/%$^£$}{%^_@~|{Test URL}

% If a real \href is wanted (also used for comparison here)
\lipsum*[3]\orighref{http://test.com/%$^£$%^_@~}{Test URL}

\end{document}
Related Question