0

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}

\newcommand\task[1]{
    \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}
\task{xb}
\end{tikzpicture}

\end{document}

Can anybody help me achieve my goal?

2
  • 1
    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
3

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

color bars

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
\keys_define:nn { mytask }
    {
        start  .int_set:N = \l_mytask_start_int,
        start  .default:n = -7,
        start  .initial:n = 0,
        color  .tl_set:N  = \l_mytask_color_tl,
        color  .default:n = {blue!20},
        color  .initial:n = black
    }
\NewDocumentCommand { \task } { O{} }
    {
      \group_begin:
      \keys_set:nn { mytask } { #1 }
    \foreach \i in {\l_mytask_start_int,...,7}{
        \draw[color=\l_mytask_color_tl] (0,0.2 * \i) -- (0.2,0.2 * \i);
    }
    \group_end:
    }
\ExplSyntaxOff


\begin{document}

\begin{frame}
\begin{tikzpicture}
\task[start=-2]
\end{tikzpicture}
\begin{tikzpicture}
\task[color=green]
\end{tikzpicture}
\begin{tikzpicture}
\task[start,color]
\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
\keys_define:nn { mytask }
    {
        start  .int_set:N = \l_mytask_start_int,
        start  .default:n = -7,
        start  .initial:n = 0,
        color  .tl_set:N  = \l_mytask_color_tl,
        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}
\task[start=-2]
\end{tikzpicture}
\begin{tikzpicture}
\task[color=green]
\end{tikzpicture}
\begin{tikzpicture}
\task[start,color]
\end{tikzpicture}
\end{frame}

\end{document}
2
  • 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);}
    – egreg
    Jan 15 '18 at 22:08
1

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}

\newcommand\task[1]{
    \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}
\task{xb}
\end{tikzpicture}

\end{document}

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.

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.