This question led to a new package:
bibleref-mouth
I am trying to write a command with an optional parameter, and feed the output to the \url
command. My motivation is to generate links to online references using the bibleref
package. That package already defined an API with optional parameters, so I don't want to change the syntax.
\url{\bibleverseurl{Amos}(3:7)}
But a command with optional arguments is apparently too fragile to be consumed by \url
. The story is in my example code.
\documentclass{article}
\usepackage{makerobust}
\usepackage{hyperref}[2011/04/09 v6.82f]
% Macro that takes an argument and encloses it in angle brackets
\protect\def\parenmatch(#1){%
MATCH$\langle#1\rangle$%
}
% Macro that does not take an argument
\protect\def\parenmismatch{%
MISMATCH%
}
% Check whether there is a parenthesis in the input, then call
% \parenmatch or \parenmismatch
\makeatletter
\newcommand*{\matcher}{%
\@ifnextchar{(}%
\parenmatch%
\parenmismatch%
}
\makeatother
% The \matcher command is probably fragile, so try to make it robust.
% Actually, I found that \matcher behaves identically to \robustmatcher
% in the examples below.
\DeclareRobustCommand{\robustmatcher}{\matcher}
\begin{document}
% This line correctly produces: MATCH<arg>
\robustmatcher(arg)
% This line correctly produces: MISMATCH!
\robustmatcher!
% This block emits an error: ! Use of \parenmatch doesn't match its definition.
% If I loosen the restrictions on the \parenmatch arguments, it
% only produces a different warning: ! Missing control sequence inserted.
% The evaluation does not respect protected commands, so it either fails to
% compile or it creates incorrect output.
% A better option is below.
\edef\problem{\robustmatcher()}
\problem
% This block correctly produces: MATCH<arg>
% As long as I use \protected@edef instead of \edef, it compiles successfully.
\makeatletter
\protected@edef\captured{\robustmatcher(arg)}
\makeatother
\captured
% Now I would like to use the command output as a link target.
% This was my goal all along.
% But the link doesn't have the address I would expect. It shows in the document as:
% \protect\let\reserved@d=(\def\defMISMATCH{MISMATCH}\futurelet\@let@token\letMATCH$\delimiter"426830Aarg\delimiter"526930B$
% I tried sprinkling \protect and \expandafter commands in the definitions and
% applications, but nothing has helped.
\url{\captured}
\end{document}
Is there something about hyperref
that is going to make this impossible? I expect that somehow I should be able to reorder the evaluations so that a plain string, already expanded, could be passed to \url
safely.
\urldef
command provided by theurl
package? Its advantage is that it creates url strings that are robust. – Mico Nov 22 '11 at 4:42\urldef\link\url{\captured}
produced the same compiler error as\url{\captured}
alone. That makes me believe that\urldef
is meant to solve a different problem. – Chad Parry Nov 22 '11 at 4:53\protect\def
should definitely be\protected\def
(eTeX's way of having protection, unrelated to LateX's\protect
). Also,\protected@edef\captured{\robustmatcher(arg)}
doesn't capture anything:\robustmatcher
is just not expanded. – Bruno Le Floch Nov 22 '11 at 5:07\url
command within the final macros:\def\urlmatcher{\@ifnextchar{(}\urlparenmatch\urlparenmismatch} \def\urlparenmatch(#1){\url{MATCH(#1)}} \def\urlparenmismatch{\url{MISMATCH!}}
. – Bruno Le Floch Nov 22 '11 at 5:12