背景
使用本网站中的一些答案,我想出了一个解决方案,用于构建一个方程式列表(带有tocloft
),以便其中两个或多个方程式可以在一个align
环境中分组和高级排版比较简单:
\documentclass{article}
\usepackage{xparse}
\usepackage{etoolbox}
\usepackage{amsmath}
\usepackage{tocloft}
\usepackage{blindtext}
% Add a new list for equations
\newcommand{\loename}{List of equations}
\newlistof{equations}{equ}{\loename}
\newcommand{\aligneqs}[2]%
{\addcontentsline{equ}{equations}{\protect\numberline{\ref{#2}}#1}}
\setlength{\cftequationsnumwidth}{2.5em}
% https://tex.stackexchange.com/q/451/53787
% https://tex.stackexchange.com/q/16883/53787
\makeatletter
% Temporary lists: store equations, references, and deferred commands
\gdef\listeqs{}
\gdef\listrefs{}
\gdef\listdefers{}
\newcounter{DeferredCommands}
% Converts a number to Roman notation
% https://tex.stackexchange.com/q/9718/53787
% https://tex.stackexchange.com/q/23487/53787
\newcommand*{\rom}[1]{\expandafter\@slowromancap\romannumeral #1@}
% Add an element to a list
\def\addtolist#1#2{%
\g@addto@macro{#1}{#2,}
}
% Add an element to a list, expanding it first
% https://tex.stackexchange.com/q/67367/53787
\def\addexpandedtolist#1#2{%
\edef\ATL@temp{\noexpand\g@addto@macro\noexpand#1{\noexpand#2,}}
\ATL@temp
}
% Defers the execution of a command, storing it in a list
\DeclareDocumentCommand{\DeferCommand}{mm}{%
\stepcounter{DeferredCommands}
\expandafter\def\csname DC@\rom{\arabic{DeferredCommands}}\endcsname{#2}
\addexpandedtolist{#1}{DC@\rom{\arabic{DeferredCommands}}}
}
% Inserts an equation, its reference, and its TOC line to their
% respective lists
\DeclareDocumentCommand{\InsertEquation}{mmm}{%
\addtolist{\listeqs}{#1}
\addtolist{\listrefs}{#3}
\DeferCommand{\listdefers}{\aligneqs{#2}{#3}}
}
% Execute all the deferred commands of the given list
% https://tex.stackexchange.com/q/28787/53787
\DeclareDocumentCommand{\DeferredExecute}{m}{%
\@for \i:=#1 \do{\@nameuse{\i}}
\setcounter{DeferredCommands}{0}
\let#1\@empty
}
% http://handyfloss.net/2007.08/latex-programming-how-to-implement-conditionals/
\newcounter{GArepnum}
\newif\ifGA@first
% Put all the equations inside a macro (first traversal) along
% with placeholders for labels, substitute the placeholders with
% their respective labels (second traversal), and show everything
% inside an "align". After it, execute all the deferred commands
% (stored when inserting an equation) that add the corresponding
% lines to the list of equations.
\DeclareDocumentCommand{\GenerateAlign}{}{%
\def\GA@ans{}
\setcounter{GArepnum}{1}
\GA@firsttrue
\@for \i:=\listeqs \do{%
% https://tex.stackexchange.com/q/53068/53787
\ifx\i\empty\else
\ifGA@first
\GA@firstfalse
\else
% https://tex.stackexchange.com/q/74707/53787
\edef\GA@temp{\noexpand\g@addto@macro\noexpand\GA@ans{\noexpand\\}}
\GA@temp
\fi
\edef\GA@temp{\noexpand\g@addto@macro\noexpand\GA@ans{\i ???}}
\GA@temp
\stepcounter{GArepnum}
\fi
}
\@for \j:=\listrefs \do{%
\ifx\j\empty\else
% https://tex.stackexchange.com/q/104506/53787
\begingroup\edef\GA@perform{\endgroup
\noexpand\patchcmd
{\noexpand\GA@ans}%
{\noexpand ???}%
{\noexpand\label{\unexpanded\expandafter{\j}}}%
{}%
{}%
}%
\GA@perform
\fi
}
\begin{align}
\GA@ans
\end{align}
\DeferredExecute{\listdefers}
\let\listeqs\@empty
\let\listrefs\@empty
}
\makeatother
\begin{document}
\listofequations
\clearpage
\section*{Important formulas}
\blindtext
\InsertEquation{a^2 + b^2 &= c^2}{Pythagorean theorem}{eq:first}
Following is eq.~\ref{eq:first}, depicting Pythagora's theorem:
\GenerateAlign
\Blindtext
\InsertEquation{e &= mc^2}{Einstein Relativity theory}{eq:second}
Following is eq.~\ref{eq:second}, depicting Einstein's relativity theory:
\GenerateAlign
\blindtext
\end{document}
问题
当使用 进行分离和编译时latexmk -pdf
,上述代码可以正常工作。但是,当尝试将此类代码集成到更大的项目(一本数学书,包含目录、参考资料等)时,我不断收到以下信息:
- 两者
TeX input capacity exceeded (sorry)
任一 Runaway argument?
考虑到该解决方案单独起作用,这样的结果很奇怪。
问题
使用列表来存储命令或其他数据(就像示例中那样)与其他包结合使用时是否容易导致堆栈耗尽?
根据答案,我将发布另一个问题,关于效率的解决方案。