5

How can I pass the optional arguments to a node being drawn in the after part of a \newenvironment*? In the before part this is easy since I can simply use #1. I tried using \edef, but that ended up with:

! Package pgfkeys Error: I do not know the key '/tikz/draw=red' and I am going to ignore it. Perhaps you misspelled it.

\documentclass[tikz,convert]{standalone}

\newenvironment*{verycontrivedexample}[1][]
{
  \node [draw=black, #1] (Before) at (0, 1) {Before};
}
{
  % This is what I'd like to do, but #1 is not available anymore
  % \node [draw=black, #1] (After) at (0, 0) {After};
}

\begin{document}
\begin{tikzpicture}

  \begin{verycontrivedexample}[draw=red]
  \end{verycontrivedexample}

\end{tikzpicture}
\end{document}
Werner
  • 603,163
Linus
  • 459

2 Answers2

8

Referencing Why can't the end code of an environment contain an argument? you need to store #1 away for the “end” part. Usually this is done by an auxiliary macro:

\newenvironment*{verycontrivedexample}[1][]
{
  \node [draw=black, #1] (Before) at (0, 1) {Before};
  \def\optargument{#1}% Store optional argument for later use.
}
{
  \node [draw=black, style/.expand once=\optargument] (After) at (0, 0) {After};
}

The style key is used to expand \optargument back to its content (otherwise you will most times end up with something like I do not know the key '/tikz/draw=red').

The same can be done with only styles, basically using the same approach:

\newenvironment*{verycontrivedexample}[1][]
{
  \node [draw=black, #1] (Before) at (0, 1) {Before};
  \tikzset{opt argument/.style={#1}}% Store optional argument for later use.
}
{
  \node [draw=black, opt argument] (After) at (0, 0) {After};
}

In both cases, the macro \optargument or the style opt argument can be accessed by the user of the environment, both unintentionally or intentionally changing/overwriting the content (easy with the style, little bit harder with the macro).

enter image description here

\documentclass[tikz,convert]{standalone}% http://ctan.org/pkg/standalone

\newenvironment*{verycontrivedexample}[1][]
{
  \node [draw=black, #1] (Before) at (0, 1) {Before};
  \def\optargument{#1}% Store optional argument for later use.
}
{
  \node [draw=black, style/.expand once=\optargument] (After) at (0, 0) {After};
}


\begin{document}
\begin{tikzpicture}

  \begin{verycontrivedexample}[draw=red]
  \end{verycontrivedexample}

\end{tikzpicture}
\end{document}
Werner
  • 603,163
6

With xparse you can refer to the parameters also in the \end part:

\documentclass[tikz]{standalone}
\usepackage{xparse}

% O{} means "optional argument with empty default"
\NewDocumentEnvironment{verycontrivedexample}{O{}}
 {\node [draw=black, #1] (Before) at (0, 1) {Before};}
 {\node [draw=black, #1] (After) at (0, 0) {After};}


\begin{document}
\begin{tikzpicture}

  \begin{verycontrivedexample}[draw=red]
  \end{verycontrivedexample}

\end{tikzpicture}
\end{document}

enter image description here

egreg
  • 1,121,712