以下 MWE 是我的项目的简化版本。\CreateMacro
用于创建表示词汇表的宏。例如,使用 body\CreateMacro{Newton}{$F=ma$}
创建。调用将打印其主体并插入类似数组的宏。\Newton
$F=ma$
\Newton
\Newton
\pushed
\Einstein
例如,如果我们已经创建了,并调用了\Einstein
,那么\Einstein
也将插入到中\pushed
。
调用\Render
将使所有元素变为\pushed
空\pushed
。
但是,我注意到有时\pushed
会受到污染,如以下输出所示。我不明白为什么\Newton
第九项仍然存在。第九项 \Newton
不应该在那里。这似乎是由竞争条件引起的。你能找出并修复它吗?
\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}
答案1
该\Newton
宏被传递给\leftmark
,因为它出现在章节标题中,所以在打印标题时对其进行评估并执行推送。
你必须消除这种行为。如果你打算做目录,也需要类似的消除。
\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}
一个可能更强大的补丁是使和执行时\push
相等。\@gobble
\@starttoc
\@outputpage
\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}
然而,在我看来,最好的做法是完全避免在标题中使用此类宏;在接下来的代码中,\CreateMacro{Newton}{$F=ma$}
定义也要\Newton*
在标题中使用,并且应该\pushNewton
在更安全的时候使用。
\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}