3

I have created the following two commands:

  • \newcommand{\pic}[1]{\begin{tikzpicture} #1 \end{tikzpicture}}
  • \newcommand{box}[1]\draw (-2,4) -- ( #1 ,4) -- ( #1 ,1) -- (-2,1) -- (-2,4) ;

In this fashion, when I invoke

\pic{
\box{0}
}

I successfully see a box.


However, when I try to create

  • \newcommand{Box}[2]\draw ( #2 ,4) -- ( #1 ,4) -- ( #1 ,1) -- ( #2 ,1) -- ( #2 ,4) ;

and hence invoke

\pic{
\Box{0,-2}
}

I see a host of errors.


What is the issue? Are there limitations on the nesting of arguments in a tikzpicture environment when using a newcommand?

  • You need a backslash in the command name: \newcommand{\Box}[2].... I'm surprised the first one worked .-. Also, you need to enclose the whole \draw ... ; in braces: {\draw ... ;} – Phelype Oleinik Jun 21 '18 at 22:17
  • 2
    The first one doesn't work, you get an error because you need a backslash before the macro name in the definition, as Phelype says (\box not box). If you fix that you get an error because \box is already defined. If you fix that (choose a different name) you get an error because you haven't wrapped the contents of the macro in {}. – Torbjørn T. Jun 21 '18 at 22:25
  • 1
    By the way, TikZ provides a macro-version of the tikzpicture environment, \tikz, you can use that instead of your \pic. – Torbjørn T. Jun 21 '18 at 22:27
  • 2
    "I successfully see a box." the code you posted could not produce output which makes the question rather hard to answer. Please always post complete code that can be run to see the issue, not just untested fragments. – David Carlisle Jun 21 '18 at 22:51

1 Answers1

10

There is a handful of problems with your code snippets:

  • You need a backslash in the command name: \newcommand{\Box}[2]...
  • You need to enclose the meaning of the command with braces: \newcommand{\Box}[2]{\draw ... ;}
  • LaTeX does not let you create a command called \box because there is already one with this name (and it's a really bad idea to redefine it).
  • Each argument to a command should be enclosed with braces, not comma-separated (if you want a comma-separated syntax, you can take a look at this thread).

The syntax to \newcommand is:

\newcommand{\<command>}[<nargs>][<default#1>]{<definition>}

Also, as Torbjørn T. noted, you don't need to define \pic because TikZ already has a macro \tikz.

That said, I'll call the commands \mybox and \myBox, then your definitions become:

\documentclass{article}

\usepackage{tikz}

\newcommand{\mybox}[1]{\draw (-2,4) -- ( #1 ,4) -- ( #1 ,1) -- (-2,1) -- (-2,4) ;}
\newcommand{\myBox}[2]{\draw ( #2 ,4) -- ( #1 ,4) -- ( #1 ,1) -- ( #2 ,1) -- ( #2 ,4) ;}

\begin{document}

\tikz\mybox{0};

\tikz\myBox{0}{-2};

\end{document}

A much more TikZ-y approach would be, as Kpym suggested, to use pic, which allows us to provide options to the drawing command as well as useput two boxes in a single command (which you cannot do easily with the approach above). You can also use the rectancle path command to make things more clear:

\documentclass{article}

\usepackage{tikz}

\tikzset{%
  pics/mybox/.style 2 args={%
    code={\draw (#1,4) rectangle (#2,1);}%
  }%
}

\begin{document}

\tikz\draw (0,0) pic{mybox={0}{-2}};

\tikz\draw (0,0) pic{mybox={0}{-2}} (2,1) pic[red]{mybox={0}{-3}};

\end{document}

another improvement would be to make all the coordinates as optional arguments with some default value, but I'll leave this for another day :)

  • Thank you for the refresher! It has been a while; I didn’t realize it was such a mess, hahaha! – gen-ℤ ready to perish Jun 22 '18 at 03:52
  • 1
    It is more in the TikZ spirit, IMO, to use pic for this : \tikzset{pics/mybox/.style 2 args={code={\draw (#1,4) rectangle (#2,1);}}} and then use it for example like this \tikz\pic{mybox={0}{-2}};. In this way you can put two boxes in a single command \tikz\draw (0,0) pic{mybox={0}{-2}} (2,1) pic[red]{mybox={0}{-3}}; – Kpym Jun 22 '18 at 05:32
  • @Kpym I have never used pic, but it's much better indeed :) I'll add a note to my answer. – Phelype Oleinik Jun 22 '18 at 11:14