# How can I remove leading and trailing spaces from a macro argument?

Consider this minimal working example:

\documentclass[a4paper]{amsart}

\usepackage{tikz}

\tikzset{graph/.style = {every node/.style = { draw,
shape = circle,
fill = black,
minimum size = 0.8mm,
inner sep = 0mm,
label distance = 0.8mm
}}}

\newcommand{\circumferencenode}[4][]{\node (#1#2) at (#4: #3) [label = #4: $#2$] {};}

\setlength{\gr}{15mm}

\begin{document}
\begin{tikzpicture}[graph]
\circumferencenode{0}{\gr}{ 90}
\circumferencenode{1}{\gr}{ 30}
\circumferencenode{2}{\gr}{330}
\circumferencenode{3}{\gr}{270}
\circumferencenode{4}{\gr}{210}
\circumferencenode{5}{\gr}{150}
\draw (0) -- (1) -- (2) -- (3) -- (4) -- (5) -- (0);
\end{tikzpicture}

\vspace*{10mm}

\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr}{ 90}
\circumferencenode{ 3}{\gr}{  0}
\circumferencenode{ 4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
\end{document}


This is what the output looks like:

As you can see, the second example is weird-looking. Something has gone wrong with the placement of nodes. I could ask why this is happening, but some experimentation shows that if the second picture is changed to the following:

\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr}{90}
\circumferencenode{3}{\gr}{0}
\circumferencenode{4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}


or even to this:

\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr} {90}
\circumferencenode {3}{\gr}  {0}
\circumferencenode {4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}


then the problem disappears, and the second graph appears the way one would expect.

So the problem is apparently the leading spaces in the arguments to the macro. I could get rid of them and do just fine. However, it is pleasing to me to arrange the calls to the \circumferencenode macro the way I did originally, so that the numbers and the sets of braces are vertically aligned. So a better solution would be to find out how to strip leading and trailing spaces from macro arguments.

• Why does the original example not work properly?
• How can I strip leading and trailing spaces from the arguments to macros I define?
-
I believe that the problem is the leading space in #2 (the first mandatory parameter) which is used to name the node. So \circumferencenode{3}{\gr}{ 0} would be ok. – Peter Grill Dec 3 '12 at 9:12

Trimming spaces can be difficult with kernel macros; here LaTeX3 can come to the rescue:

\documentclass[a4paper]{amsart}

\usepackage{tikz,xparse}

\tikzset{graph/.style = {every node/.style = { draw,
shape = circle,
fill = black,
minimum size = 0.8mm,
inner sep = 0mm,
label distance = 0.8mm
}}}

%%% We need a "classical" definition, because of the colons in the replacement text
\newcommand{\circumferencenodeinner}[4]{\node (#1#2) at (#4: #3) [label = #4: $#2$] {};}
%%% Now we go with LaTeX3
\ExplSyntaxOn
\NewDocumentCommand{\circumferencenode}{ O{} m m m }
{
\hammerite_circumference_node:nxnx
{ #1 }
{ \tl_trim_spaces:n { #2 } }
{ #3 }
{ \tl_trim_spaces:n { #4 } }
}
\cs_set_eq:NN \hammerite_circumference_node:nnnn \circumferencenodeinner
\cs_generate_variant:Nn \hammerite_circumference_node:nnnn { nxnx }
\ExplSyntaxOff

\setlength{\gr}{15mm}

\begin{document}

\noindent\begin{minipage}{.4\textwidth}
%%% Just to give an example we use the old definition
\newcommand{\circumferencenodeold}[4][]{\node (#1#2) at (#4: #3) [label = #4: $#2$] {};}

\textbf{Old}

\begin{tikzpicture}[graph]
\circumferencenodeold{0}{\gr}{ 90}
\circumferencenodeold{1}{\gr}{ 30}
\circumferencenodeold{2}{\gr}{330}
\circumferencenodeold{3}{\gr}{270}
\circumferencenodeold{4}{\gr}{210}
\circumferencenodeold{5}{\gr}{150}
\draw (0) -- (1) -- (2) -- (3) -- (4) -- (5) -- (0);
\end{tikzpicture}

\vspace*{10mm}

\begin{tikzpicture}[graph]
\circumferencenodeold{02}{\gr}{ 90}
\circumferencenodeold{ 3}{\gr}{  0}
\circumferencenodeold{ 4}{\gr}{270}
\circumferencenodeold{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
\noindent\begin{minipage}{.4\textwidth}
\textbf{New}

\begin{tikzpicture}[graph]
\circumferencenode{0}{\gr}{ 90}
\circumferencenode{1}{\gr}{ 30}
\circumferencenode{2}{\gr}{330}
\circumferencenode{3}{\gr}{270}
\circumferencenode{4}{\gr}{210}
\circumferencenode{5}{\gr}{150}
\draw (0) -- (1) -- (2) -- (3) -- (4) -- (5) -- (0);
\end{tikzpicture}

\vspace*{10mm}

\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr}{ 90}
\circumferencenode{ 3}{\gr}{  0}
\circumferencenode{ 4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
\end{minipage}
\end{document}


The command \circumferencenodeinner is defined in the standard way because of the colons in its replacement text; notice that no optional argument is specified; it's only a helper macro that will be \let to a macro with a LaTeX3 name, so that the variant with suffix nxnx can be created; the x means that the corresponding argument is completely expanded. Indeed when we finally call it, arguments #2 and #4 are passed to \tl_trim_spaces:n whose job is exactly to trim leading and trailing spaces, then passing the rest as is.

-
Such arcane wizardry is beyond my comprehension... – Hammerite Dec 3 '12 at 11:56
@Hammerite There would be a method also with "classical LaTeX" macros, but it's involved and lengthy. – egreg Dec 3 '12 at 12:31

As Peter Grill said, there is a conflict between the node name as defined by the \circumferencenode command and the name of the node used when drawing the graph. The answer to the first question is, then, that you are defining node " 3" (note the leading space) and using node (3) without the leading space.

This is the draw command that should be used with the definitions provided:

 \draw (02) -- ({ 3}) -- ({ 4}) -- (15) -- (02);


I don't know a simple answer to the second question :(.

-