# How can I use IfSubStr in a loop or an optional argument?

I'm trying to define a command for use in a tikz picture that changes its appearance based on characters in an option string.

Here's a simple example. I want either 8 or 15 lines drawn, depending on whether the option "x" is specified, and I want to change the color of the lines depending on whether the option "b" is specified.

Here's my code (it doesn't compile)

\documentclass{beamer}
\usepackage{xstring}

\usepackage{tikz}

\begin{document}

\foreach \i in {\IfSubStr{#1}{x}{0}{-7},...,7}{
\draw[\IfSubStr{#1}{b}{color=blue!20}] (0,0.2 * \i) -- (0.2,0.2 * \i);
}
}

\begin{tikzpicture}
\end{tikzpicture}

\end{document}


Can anybody help me achieve my goal?

• You can't this way in the \foreach header, most likely, since \IfSubStr is unexpandable
– user31729
Jan 15 '18 at 18:38
• The 2nd \IfSubStr is incomplete, by the way
– user31729
Jan 15 '18 at 18:45

Just one way to make it (a) more flexible and (b) work:

I've used a key-value approach for this. You can easily adapt your default preference and even pass own values to your keys.

\documentclass{beamer}

\usepackage{tikz}

\usepackage{expl3,xparse}
\ExplSyntaxOn
{
start  .default:n = -7,
start  .initial:n = 0,
color  .default:n = {blue!20},
color  .initial:n = black
}
\NewDocumentCommand { \task } { O{} }
{
\group_begin:
\keys_set:nn { mytask } { #1 }
\draw[color=\l_mytask_color_tl] (0,0.2 * \i) -- (0.2,0.2 * \i);
}
\group_end:
}
\ExplSyntaxOff

\begin{document}

\begin{frame}
\begin{tikzpicture}
\end{tikzpicture}
\begin{tikzpicture}
\end{tikzpicture}
\begin{tikzpicture}
\end{tikzpicture}
\end{frame}

\end{document}


Thanks to @egreg a more expl3-ish version (I don't replace my former code, because using the foreach is still fine):

\documentclass{beamer}

\usepackage{tikz}

\usepackage{expl3,xparse}
\ExplSyntaxOn
{
start  .default:n = -7,
start  .initial:n = 0,
color  .default:n = {blue!20},
color  .initial:n = black
}
\NewDocumentCommand { \task } { O{} }
{
\group_begin:
\keys_set:nn { mytask } { #1 }
\int_step_inline:nnnn { \l_mytask_start_int } { 1 } { 7 }
{
\draw[color=\l_mytask_color_tl] (0,0.2 * ##1) -- (0.2,0.2 * ##1);
}
\group_end:
}
\ExplSyntaxOff

\begin{document}

\begin{frame}
\begin{tikzpicture}
\end{tikzpicture}
\begin{tikzpicture}
\end{tikzpicture}
\begin{tikzpicture}
\end{tikzpicture}
\end{frame}

\end{document}

• Thank you! I came up with something else that doesn't use expl3, which I had never heard of until I read your answer. I'll have to study this new syntax more before I can intelligently comment further. Jan 15 '18 at 21:18
• And then you don't need \foreach: \int_step_inline:nnnn { \l_mytask_start_int}{1}{7}{\draw[color=\l_mytask_color_tl] (0,0.2 * ##1) -- (0.2,0.2 * ##1);} Jan 15 '18 at 22:08

I was playing with this some more, and I've figured out that even though I can't use \IfSubStr in an \edef, I can use \edef in an \IfSubStr.

So I've now got this:

\documentclass{beamer}
\usepackage{xstring}

\usepackage{tikz}

\begin{document}

\IfSubStr{#1}{x}{\edef\starti{0}}{\edef\starti{-7}}
\IfSubStr{#1}{b}{\edef\drawcolor{blue!20}}{\edef\drawcolor{}}

\foreach \i in {\starti,...,7}{
\draw[\drawcolor] (0,0.2 * \i) -- (0.2,0.2 * \i);
}
}

\begin{tikzpicture}

Not sure why I can't put color=blue!20 in that second \edef (instead of just blue!20), but it works the way it is.