3

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:

Vertical Line in the middle of the 'h' in 'hello'.

(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?

3

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}

enter image description here

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
  • 1
    @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
  • 1
    @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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.