# Using variables in a command results in ! Argument of \reserved@a has an extra }

I want to define a command, which separates a string an later adds a different \href to the first part, than to the second (e.g. \qname{foaf:Person}). But the code as I have it doesn't work, I get ! Argument of \reserved@a has an extra }., when I try to run it.

\RequirePackage{xstring}
\RequirePackage{hyperref}
\RequirePackage{url}

\newcommand{\prefix}{}%
\newcommand{\postfix}{}%
\newcommand{\qname}[1]{%
\IfSubStr{#1}{:}{%
\renewcommand{\prefix}{\StrBefore{#1}{:}}%
\renewcommand{\postfix}{\StrBehind{#1}{:}}%
}{%
\url{#1}%
}%
}


If I just output \prefix instead of \nolinkurl{\prefix}:\nolinkurl{\postfix} it works, but I want to have it as url.

I think there is something wrong with the variable handling, but I couldn't find information about this.

Please always post a complete document not just a fragment.

\show\prefix


you will see it is not exactly the characters before : it is

> \prefix=\long macro:
->\StrBefore {a:b}{:}.


Which presumably does not expand to something hyperref likes.

This version just uses an expandable macro to split on :

\documentclass{article}

\RequirePackage{xstring}
\RequirePackage{hyperref}
\RequirePackage{url}

\newcommand{\prefix}{}%
\newcommand{\postfix}{}%
\newcommand{\qname}[1]{%
\IfSubStr{#1}{:}{%
\renewcommand{\prefix}{\StrBefore{#1}{:}}%
\renewcommand{\postfix}{\StrBehind{#1}{:}}%
\show\prefix
}{%
\url{#1}%
}%
}

\def\qname#1{\xqname#1:\valign:\\}

\def\xqname#1:#2:#3\\{%
\ifx\valign#2%
\else
\fi}

\begin{document}

\qname{aaa}

\qname{a:b}

\end{document}

• Thank you very much for your answer. But I don't really understand, what it is doing. Does the \def part just replace my definition? (BTW: the else-case \url{#1} is not needed) – white_gecko May 16 '13 at 16:47
• @white_gecko It splits on : by making a delimited argument so #1 is everythig up to teh first : you can not define such arguments with \newcommand. I left in your definition but with \show added, if you comment out my later definition you will see the \show output that I showed above – David Carlisle May 16 '13 at 16:50
• ok, and what is the \valign and the #3 for? I only use #1 and #2 as I think. I have now simplified the \xqname to \def\xqname#1:#2:#3\\{ \href{http://#1}{\nolinkurl{#1:}} \href{http://#1#2}{\nolinkurl{#2}} } – white_gecko May 16 '13 at 17:02
• Your simplified version only works if there is a : the \valign is just an arbitrary token unlikely to be in the input so if that is the token after : there was no : originally and the second \nolinkur; is not used – David Carlisle May 16 '13 at 17:06
• That is fine the argument has to contain a :. I've removed the \valign and #3 now. Am I right, that the \ is some arbidrary char as end of the command? – white_gecko May 16 '13 at 17:16

It's not clear why you want to split at the colon; however, this is a different way to cope with the problem.

\documentclass{article}
\usepackage{xparse,l3regex}
\usepackage{hyperref}

\ExplSyntaxOn
\tl_new:N \l_gecko_prefix_tl
\tl_new:N \l_gecko_postfix_tl
\NewDocumentCommand{\qname}{m}
{
\regex_match:nnTF { \: } { #1 }
{
\tl_set:Nn \l_gecko_prefix_tl { #1 }
\tl_set:Nn \l_gecko_postfix_tl { #1 }
\regex_replace_once:nnN { \A (.*) \: (.*) \Z } { \1 } \l_gecko_prefix_tl
\regex_replace_once:nnN { \A (.*) \: (.*) \Z } { \2 } \l_gecko_postfix_tl
}
{\url{#1}}
}\ExplSyntaxOff

\begin{document}
\qname{foo:bar}

\qname{http://tex.stackexchange.com}

\qname{127.0.0.1}
\end{document}


Not sure if this addresses your issue. It uses the stringstrings package to parse the string.

\documentclass{article}
\RequirePackage{stringstrings}
\usepackage{ifthen}
\RequirePackage{hyperref}
\RequirePackage{url}

\newcommand{\prefix}{}%
\newcommand{\postfix}{}%
\newcounter{index}
\newcommand{\qname}[1]{%
\whereischar[q]{#1}{:}%
\setcounter{index}{\theresult}%
\ifthenelse{\value{index} = 0}%
{\url{#1}}%
{%
\substring[q]{#1}{1}{\value{index}}%
\edef\prefix{\thestring}%
\substring[q]{#1}{\value{index}}{\$}%
\edef\postfix{\thestring}%