# String operation creates error in pgfmathsetmacro

I am trying to reference the first character of a string within a pgfmathsetmacro, however, the macro \StrLeft from xstring, I believe, is not playing well with pgfmathsetmacro.

Take the following example that replicates this problem:

    \documentclass{article}
\usepackage{tikz}
\usepackage{xstring}

\begin{document}

\begin{tikzpicture}
\newcommand{\str}{hello};
\newcommand{\firstChar}
{
\StrLeft{\str}{1}
};

\pgfmathsetmacro{\halfStr}{width("\str") * 1pt / 2cm};
\pgfmathsetmacro{\halfFirstChar}{width("\firstChar") * 1pt / 2cm};

\node at (0, 0) {\str};
\draw [color=black] (\halfFirstChar - \halfStr, 0cm) -- (\halfFirstChar - \halfStr,-1cm);
\end{tikzpicture}

\end{document}


The following code should output the following:

(The string "hello" printed, along with a vertical line beginning from the halfway point of the "h" character and then moving downwards 1 centimeter.)

However, \halfFirstChar generates an error that reads:

Argument of \reserved@a has an extra }. Runaway argument? Extra }, or forgotten \endgroup.

I am able to print \firstChar without any problems by doing the following:

    % ...
\node at (0, 0) {\firstChar};
% ...


However, I am unable to reference \firstChar within \halfFirstChar. Does anyone have any idea what might be causing this error and a solution to this problem?

This is a bit tricky because of expansion issues. The perhaps easiest way to make it work is to use the optional argument of \StrLeft to define \firstChar. Then the rest works as it should, I think.

\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}

\begin{document}

\begin{tikzpicture}
\newcommand{\str}{hello}
\StrLeft{\str}{1}[\firstChar]
\pgfmathsetmacro{\halfStr}{width("\str") * 1pt / 2cm};
\pgfmathsetmacro{\halfFirstChar}{width("\firstChar") * 1pt / 2cm};

\node at (0, 0) {\str};
\draw [color=black] (\halfFirstChar - \halfStr, 0cm) -- (\halfFirstChar - \halfStr,-1cm);
\end{tikzpicture}
\end{document}


I believe to also sense where the journey may go. You need to be a bit careful since nodes have outer and inner seps, which may affect the position, but you can set those to 0. And actually you do not need the \pgfmathsemacro thingy, the TikZ parser is very versatile, it even understands pts:

\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}

\begin{document}

\begin{tikzpicture}
\newcommand{\str}{hello}
\StrLeft{\str}{1}[\firstChar]
\node[inner sep=0] at (0, 0) {\str};
\draw [color=black] ({(width("\firstChar")/2-width("\str")/2)*1pt}, 0cm)
-- ++ (0,-1cm);
\end{tikzpicture}
\end{document}


And of course you can change the font size in nodes, which may also affect these tricks. I am actually wondering if you want to have a look at the tikzmark library and check what has been done there. (BTW, you need no ; after \newcommand{...}{...}.)

• What do you mean by "expansion issues?" I guess I am confused about what sort of syntax and/or "rules" I am breaking in LaTeX when I wrote my original example above? – Code Doggo Oct 10 '18 at 5:34
• @DanHoynoski Certainly a comment and not even a full answer will provide enough space to answer that. Here is an answer to that. Basically if you have \macro{\anothermacro} it matters if \anothermacro is "expanded" or some "hull" that expands to something when you, well, expand it. Please have a look at the link... ;-) – user121799 Oct 10 '18 at 5:39
• @DanHoynoski Basically, \StrLeft is a set of instructions to typeset the left-most character, which is not the same as the character itself. – Joseph Wright Oct 10 '18 at 6:02