# biblatex: only wrap url string in \url if it is not already wrapped that way

I am using a customized BibLaTeX bibliography style in which I use the following macro: \newbibmacro{archive}[1]{\\\textsc{Archived:}\ \url{#1}}.

I use this to format certain urls, it is called from other macros with a string (normally "http://www.somesite.com") as argument. This works fine.

However, for reasons beyond my control, sometimes the string I need to pass to the macro is already in the form "\url{http://www.somesite.com}". This means that my macro then generates \\\textsc{Archived:}\ \url{\url{http://www.somesite.com}}, which of course results in a latex compilation error due to the nested \url.

So, my question is: how can I change the above macro such that it only wraps its argument (#1) in \url if it is not already wrapped that way?

EDIT: MWE's to clarify my problem with egreg's answer

Although my original macro causes compilation problems in case of double wrapped url's, its presence in my bbx file does not break compilation on its own. For example, this compiles fine:

\documentclass{article}

\usepackage{filecontents}

\begin{filecontents}{test.bbx}
\ProvidesFile{test.bbx}
\RequireBibliographyStyle{numeric-comp} %in turn that one requires standard.bbx
\newbibmacro{archive}[1]{\\\textsc{Archived:}\ \url{#1}}
\end{filecontents}

\usepackage[bibstyle=test]{biblatex}

\begin{document}
Blah blah
\end{document}

However, when I put egreg's solution in a bbx file (which is were I want it to be because this macro is part of my custom bibliography style), it causes a compilation error (even if the macro is not called). Hence, this does not compile:

\documentclass{article}

\usepackage{filecontents}

\begin{filecontents}{test.bbx}
\ProvidesFile{test.bbx}
\RequireBibliographyStyle{numeric-comp} %in turn that one requires standard.bbx
\makeatletter
\newbibmacro{archive}[1]{\\\textsc{Archived:} \test@URL#1\@nil}
\def\test@URL{\@ifnextchar\url\test@URL@i\test@URL@ii}
\def\test@URL@i#1\@nil{#1}
\def\test@URL@ii#1\@nil{\url{#1}}
\makeatother
\end{filecontents}

\usepackage[bibstyle=test]{biblatex}

\begin{document}
Blah blah
\end{document}

I guess this due to that \makeatletter/other stuff? I have never quite understood what that is for :-)

-
Yes, the problem is exactly in \makeatletter and \makeatother: you don't need them in a .bbx file. –  egreg Feb 7 '12 at 18:31
If the reason beyond your control for there already being a \url{} in the string is that your .bib data contains this, they you can use Biber's sourcemap functionality to regularise your data stream without having to actually edit it. –  PLK Feb 7 '12 at 20:28

\makeatletter
\newbibmacro{archive}[1]{\\\textsc{Archived:} \test@URL#1\@nil}
\def\test@URL{\@ifnextchar\url\test@URL@i\test@URL@ii}
\def\test@URL@i#1\@nil{#1}
\def\test@URL@ii#1\@nil{\url{#1}}
\makeatother


The macro \test@URL peeks at the next token to see if it is \url. So we can see the two cases

\usebibmacro{archive}{http://www.somesite.com}
\usebibmacro{archive}{\url{http://www.somesite.com}}


Case 1: we get

\\\textsc{Archived:} \test@URL http://www.somesite.com\@nil


Then \test@URL doesn't find \url, so it executes

\test@URL@ii http://www.somesite.com\@nil


which becomes

\url{http://www.somesite.com}


(the argument to \test@URL@ii is everything up to \@nil).

Case 2: we get

\\\textsc{Archived:} \test@URL \url{http://www.somesite.com}\@nil


Then \test@URL does find \url, so it executes

\test@URL@i \url{http://www.somesite.com}\@nil


which becomes

\url{http://www.somesite.com}


(again, the argument to \test@URL@i is everything up to \@nil).

-
Apparently this does not work when I put it in my bbx(biblatex bibliograph style) file. Maybe because of the \makeatletter? –  Matthias Feb 7 '12 at 11:39
Or maybe it would be better to just add the non-wrapping-twice fix at the latex level by redefining \url before I load biblatex? And then use my original macro. Would that work? –  Matthias Feb 7 '12 at 11:44
It's difficult to say without a minimal example –  egreg Feb 7 '12 at 13:02
I just added two MWEs to clarify what I mean. –  Matthias Feb 7 '12 at 18:15