Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
1  
The most straightforward solution is just to use \# instead of #. I’m not sure the benefits from your solution justify going the extra mile here: even in HTML (which was, after all, developed in close connection with the URL syntax), when you want to use such URLs you have to manually escape parts of them. –  Konrad Rudolph Mar 7 '11 at 16:46
    
you could just use an URL shortener like is.gd to get an URL without special characters... –  Habi Mar 7 '11 at 17:20
2  
@Konrad: but we built computers to do things for us! –  Mariano Suárez-Alvarez Jul 23 '11 at 17:41
    
@Andrew: Note my updated answer (now even easier!) ;-) –  Martin Scharrer Jul 26 '11 at 23:09

4 Answers 4

up vote 13 down vote accepted

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}
share|improve this answer
    
I think that you should add this as a solution to the original question as well. –  Loop Space Mar 7 '11 at 18:56
    
@Andrew: done + added explanation how to define macros which read an argument verbatim. –  Martin Scharrer Mar 7 '11 at 19:11

Use the bigfoot package:

\documentclass{article}
\usepackage{bigfoot}
\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}

Unfortunately this doesn't seem to work to solve the original questioner's problem, since putting this into another macro definition seems to break it.

share|improve this answer
1  
Nonetheless, it answers the question that I actually asked and is a simpler method if one doesn't want to wrap it in a new macro. Thanks. –  Loop Space Mar 8 '11 at 14:06

This definition seems to work with the hyperref package. \hyper@normalise takes care of all those nasty characters.

\makeatletter
\newcommand\myhref@[2]{#2\footnote{\url@{#1}}}
\DeclareRobustCommand{\myhref}{\hyper@normalise\myhref@}
\makeatother

Edit: This typesets the link as a footnote. To just get a footnote with a link labelled by the text in the second argument, this should work:

\makeatletter
\newcommand\hreffootnote@[2]{\footnote{\hyper@linkurl{\Hurl{#2}}{#1}}}
\DeclareRobustCommand{\hreffootnote}{\hyper@normalise\hreffootnote@}
\makeatother

share|improve this answer
    
Useful to know, but it doesn't quite emulate what \footnote{\href{a}{b}} should do as \href{a}{b} creates a link to a with the text b so the URL isn't visible in the document. –  Loop Space Mar 9 '11 at 21:28
    
Thanks, I misunderstood. See my new solution above. –  Michael Ummels Mar 10 '11 at 0:37
    
Nice answer. I forgot that hyperref gives you \hyper@normalise which does basically the same as the code in my answer, but does it for you. –  Martin Scharrer Mar 10 '11 at 10:45

Disclaimer: do not use this answer: the "bigfoot" answer above is (probably) much better.

My idea is to make # active document-wide, and let it to a macro parameter character, so that it can still be used in definitions (e.g. in the definition of \href). In the troublesome parts, we can disable the #: simply \let it to be equal to \relax, in other words, to do nothing.

The only reason why we cannot make # active before loading hyperref is that this package itself makes # active, and for some reason that I did not track down, hyperref is not happy with it.

\documentclass{article}
\usepackage{hyperref}

\makeatletter
\let \macro@parameter@character #
\catcode`\#=13
\let #\macro@parameter@character
\let\href@old\href
\renewcommand{\href}[2]{\footnote{\let##\relax\href@old{#1}{#2}}}
\makeatother

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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.