# Expanding a sequence inside a TikZ path

I am trying to draw a simple path using TikZ, with a custom syntax to specify it. This works:

\documentclass{article}
\usepackage{tikz}
\begin{document}

\newcommand{\latticepath}[1]{
\draw[thick] (0,0) node{} \foreach \x in {#1}{ -- \if u\x ++(0,1) \else ++(1,0) \fi node{}};
}
\begin{tikzpicture}[x=3mm,y=3mm]
\tikzset{every node/.style={circle,fill,draw=none,inner sep=2pt}}
\latticepath{r,r,u,r,r,u,u,r,u,r,u,u}
\end{tikzpicture}

\end{document}

However, I would prefer not to comma-separate the values. So I wrote this command to convert a sequence of letters into path components:

\documentclass{article}
\usepackage{tikz}
\begin{document}

\makeatletter\let\mygobble\@gobble\makeatother
\def\pathimpl##1{\ifx##1.\let\rest\mygobble\else\ifx##1u#1\else#2\fi\def\rest####1{####1}\fi\rest\pathimpl}
\pathimpl#3.
}

However this implementation produces a bunch of errors due to the use of macros in paths:

\newcommand{\betterlatticepath}[1]{
\draw[thick] (0,0) node{} \readpath{++(0,1) node{}}{++(1,0) node{}}{#1};
}
\begin{tikzpicture}
\tikzset{every node/.style={circle,fill,draw=none,inner sep=2pt}}
\betterlatticepath{rrurruururuu}
\end{tikzpicture}

\end{document}

Package tikz Error: Giving up on this path. Did you forget a semicolon?.
Undefined control sequence.
You can't use `macro parameter character #' in restricted horizontal mode.
Parameters must be numbered consecutively.
Parameters must be numbered consecutively.
Argument of \rest has an extra }.
Runaway argument?

I tried \pgfextra, but this doesn't help. How can I make this work?

-
Please make your code compilable (if possible), or at least complete it with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem tedious to you, but think of the extra work it represents for TeX.SX users willing to give you a hand. Help them help you: remove that one hurdle between you and a solution to your problem. – Jubobs Feb 9 '14 at 12:07

Here is a solution using \pgfextra, insert path and two custom keys:

\documentclass[tikz]{standalone}

\tikzset{
recurse lattice path/.code args={#1#2}{
\ifx#1.
\else
\ifx#1u
\tikzset{insert path={-- ++(0,1) node[fill=black]{}}}
\else
\tikzset{insert path={-- ++(1,0) node[fill=black]{}}}
\fi
\tikzset{recurse lattice path=#2}
\fi
},
lattice path/.code={%
\draw (0,0) node[fill=black]{}
\pgfextra{\tikzset{recurse lattice path={#1.}}};
},
}

\begin{document}
\begin{tikzpicture}
\tikzset{lattice path=rrurrur}
\end{tikzpicture}
\end{document}

Edit:

Here is a simpler solution without \pgfextra:

\documentclass[tikz]{standalone}

\tikzset{
dep u/.style={insert path={-- ++(0,1) node{}}},
dep r/.style={insert path={-- ++(1,0) node{}}},
dep d/.style={insert path={-- ++(0,-1) node{}}},
dep l/.style={insert path={-- ++(-1,0) node{}}},
recurse lattice path/.code args={#1#2}{
\ifx#1.\else\tikzset{dep #1,recurse lattice path=#2}\fi
},
lattice path/.style={recurse lattice path=#1.}
}

\begin{document}
\begin{tikzpicture}
\tikzset{every node/.style={circle,fill,draw=none,inner sep=2pt}}
\draw (0,0) node{} [lattice path=rrurrurrdddlll];
\end{tikzpicture}
\end{document}
-
Thanks, this is great! But I don't quite understand how the code args part works. Why does #1 get the first character while #2 gets the entire remaining path? – jtbandes Feb 9 '14 at 20:14
@jtbandes That's basically how TeX works with delimited macros. Try \tt \def\parse#1#2\eov{arg 1 -> (#1); arg 2 -> (#2);} \parse123456789\eov. It is basically what is happening inside \pgfkeys. – Mark Wibrow Feb 10 '14 at 7:12
@MarkWibrow That makes sense, I just didn't the code args setting is a delimited macro (since it just says #1#2 and not #1#2.). – jtbandes Feb 11 '14 at 4:07

Basically, you can't put a macro defined using \newcommand inside a TikZ path as it does a lot of stuff "under the covers" (e.g., \futurelet) which TikZ cannot handle.

You can, however, put arbitrary code inside \pgfextra{} in a TikZ path. In this case you could build the path inside \pgfextra and then insert it afterwards, like this:

\documentclass[tikz,border=0.125cm]{standalone}

\expandafter\def\expandafter\latticepath\expandafter{\latticepath#1}%
}

\def\parselatticepath#1{%
\def\latticepath{node {}}%
\Parselatticepath#1@}
\def\Parselatticepath#1{%
\ifx#1@%
\let\next=\relax%
\else%
\csname latticepathletter#1\endcsname%
\let\next=\Parselatticepath
\fi%
\next}

\tikzset{%
insert lattice path/.style={%
every node/.style={
circle,
fill,
draw=none,
inner sep=2pt
},
insert path={%
\pgfextra{\parselatticepath{#1}}%
\latticepath
}
}
}

\begin{document}
\begin{tikzpicture}
\draw (0,0) [insert lattice path={rrurruururuu}];
\end{tikzpicture}
\end{document}

-