3

The following MWE is the simplified version of my project. \CreateMacro is used to create macros representing vocabularies. For example, \CreateMacro{Newton}{$F=ma$} creates \Newton with body $F=ma$. Invoking \Newton will print its body as well as insert \Newton into an array-like macro \pushed.

If we have created \Einstein, for example, and invoke \Einstein, then \Einstein will also be inserted into \pushed.

Invoking \Render will render all elements of \pushed and make \pushed empty.

However, I notice that sometimes \pushed gets contaminated as shown in the following output. I don't understand why \Newton still exists in the ninth item. In the ninth item \Newton should not be there. It seems to be caused by a race condition. Could you figure out and fix it?

enter image description here

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}


\def\Format#1{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}




\newcommand\CreateMacro[2]{%
    \expandafter\newrobustcmd\csname#1\endcsname{#2\gappto\pushed{\Format{#2}}}%
}


\gdef\Render{%
    \Table
        \pushed
    \endTable
    \gdef\pushed{}%
}




\begin{document}
\CreateMacro{Newton}{$F=ma$.}

\chapter{\Newton}
\Render


\begin{enumerate}
    \item 
    \CreateMacro{Einstein}{$E=mc^2$}
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}
  • can you say what the intention of the code is, why the need for the regex replace? It makes it hard if you just post a lot of code and say it does the wrong thing without saying what the right thing is. – David Carlisle Dec 2 '15 at 16:36
5

The \Newton macro is passed to the \leftmark, because it appears in the chapter title, so it's evaluated when printing the heading and does a push.

You have to neutralize this behavior. A similar neutralization is needed if you plan to do the table of contents.

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}
\usepackage{environ}
\usepackage{xparse}

\makeatletter
\renewcommand{\chaptermark}[1]{%
  \markboth{%
    % don't push as result of evaluating the heading
    \let\noexpand\push\noexpand\@gobble
    % the standard definition follows
    \MakeUppercase{%
      \ifnum\c@secnumdepth>\m@ne
        \if@mainmatter
          \@chapapp\ \thechapter. \ %
        \fi
      \fi
      #1%
    }%
  }{}%
}
\makeatother


\newcommand\Format[1]{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}

\newcommand\CreateMacro[2]{%
  \expandafter\newrobustcmd\csname#1\endcsname{#2\push{\Format{#2}}}%
}

\newcommand\push[1]{\gappto\pushed{#1}}

\newcommand\Render{%
    \begin{Table}
        \pushed
    \end{Table}%
    \gdef\pushed{}%
}

\begin{document}
\CreateMacro{Newton}{$F=ma$.}
\CreateMacro{Einstein}{$E=mc^2$}

\chapter{\Newton}
\Render


\begin{enumerate}
    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}

enter image description here

A possibly more robust patch is to make \push equal to \@gobble when \@starttoc and \@outputpage are executed.

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}
\usepackage{environ}
\usepackage{xparse}

\makeatletter
\patchcmd{\@starttoc}{\begingroup}{\begingroup\let\push\@gobble}{}{}
\patchcmd{\@outputpage}{\begingroup}{\begingroup\let\push\@gobble}{}{}
\makeatother

\newcommand\Format[1]{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}

\newcommand\CreateMacro[2]{%
  \expandafter\newrobustcmd\csname#1\endcsname{#2\push{\Format{#2}}}%
}

\newcommand\push[1]{\gappto\pushed{#1}}

\newcommand\Render{%
    \begin{Table}
        \pushed
    \end{Table}%
    \gdef\pushed{}%
}

\begin{document}
\CreateMacro{Newton}{$F=ma$.}
\CreateMacro{Einstein}{$E=mc^2$}

\tableofcontents

\chapter{\Newton}
\Render


\begin{enumerate}
    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}

However, the best way to proceed would be, in my opinion, avoiding such macros in titles altogether; in the code that follows, \CreateMacro{Newton}{$F=ma$} defines also \Newton* to be used in titles, which should be followed by \pushNewton at a safer time.

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}
\usepackage{environ}
\usepackage{xparse}
\usepackage{atbegshi}

\newcommand\Format[1]{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}

\makeatletter
\newcommand\CreateMacro[2]{%
  \expandafter\newrobustcmd\csname#1\endcsname{%
    \@ifstar{\@nameuse{#1star}}{\@nameuse{#1nostar}}%
  }%
  \@namedef{#1nostar}{#2\push{\Format{#2}}}%
  \@namedef{#1star}{#2}% \global\toggletrue{#1}}%
  \@namedef{push#1}{\push{\Format{#2}}}%
}
\makeatother

\newcommand\push[1]{\gappto\pushed{#1}}

\newcommand\Render{%
    \begin{Table}
        \pushed
    \end{Table}%
    \gdef\pushed{}%
}

\begin{document}
\CreateMacro{Newton}{$F=ma$.}
\CreateMacro{Einstein}{$E=mc^2$}

\tableofcontents

\chapter{\Newton*}\pushNewton
\Render


\begin{enumerate}
    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}
  • Could you please fix the table of contents issue as well? – Money Oriented Programmer Dec 3 '15 at 11:35
  • 1
    @YasashiiEirian I made a couple of proposals; the best option, in my opinion, is the last one, because it's independent from packages used that could modify \@starttoc or \@outputpage. – egreg Dec 3 '15 at 13:16

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.