问题

问题

问题

我有兴趣获得以下结果,通过不是直接用代码编写。

\begin{align}
    T(x) &= ae^{-\frac{(x-b)^2}{2c^2}} \\
    \frac{1}{2} < a &\leq 1 \label{eq:m1va} \\
    b &= \SI{25}{\degreeCelsius} \label{eq:m1vb} \\
    c &= \frac{5}{\sqrt{2 \ln{2a}}} > 0 \label{eq:m1vc}
\end{align}
\aligneqs{Model 1: Condition 1}{eq:m1va}
\aligneqs{Model 1: Condition 2}{eq:m1vb}
\aligneqs{Model 1: Condition 3}{eq:m1vc}

该命令aligneqs在序言中定义如下:

\usepackage{tocloft}
\newcommand{\loename}{List of equations}
\newlistof{equations}{equ}{\loename}
\newcommand{\aligneqs}[2]% <=== HERE
    {\addcontentsline{equ}{equations}{\protect\numberline{\ref{#2}}#1}}

我心中的总体想法是能够写align如下内容:

\InsertEquation{T(x) &= ae^{-\frac{(x-b)^2}{2c^2}}}{Model 1: Base formula}{eq:m1gauss}
\InsertEquation{\frac{1}{2} < a &\leq 1}{Model 1: Condition 1}{eq:m1va}
\InsertEquation{b &= \SI{25}{\degreeCelsius}}{Model 1: Condition 2}{eq:m1vb}
\InsertEquation{c &= \frac{5}{\sqrt{2 \ln{2a}}} > 0}{Model 1: Condition 3}{eq:m1vc}
\GenerateAlign

先前的结果

我实际上已经想出了一个解决方案,在这个问题,但仅在单独测试时才有效(即不包含其他包)。

我在这里附上代码以防其他问题被关闭:

\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}

可以看出,命令执行(\aligneqss)在某个时刻被推迟了。当方程式被“声明”时,它被存储在一个列表中,连同引用(在另一个列表中)和要推迟的命令(在另一个列表中)。

一旦它们被收集起来,使用\@for循环,将方程式插入到宏中(带有标签占位符),然后使用另一个\@for循环,将占位符替换为其相应的标签。

最后,align排版并最后,延迟的命令最终被执行(在方程列表中插入行)。

问题

鉴于它只有在单独测试时才有效,有没有更好的方法来推迟命令的执行?

答案1

已编辑以处理使用\allowdisplaybreaks

\documentclass{article}
\usepackage{amsmath,siunitx,tocloft,lipsum}
\newcommand{\loename}{List of equations}
\newlistof{equations}{equ}{\loename}
\makeatletter
\newcommand{\aligneqs}[2]{\addcontentsline{equ}{equations}{\protect\numberline{\ref{#2}}#1}}
\newcommand\aligngroup{}
\newcommand\GenerateAlign{\expandafter\GenerateAlignaux\aligngroup\relax}
\def\GenerateAlignaux#1\\\relax{\begin{align}#1\end{align}\gdef\aligngroup{}}
\newcommand\InsertEquation[3]{%
  \g@addto@macro\aligngroup{\aligneqs{#2}{#3}#1\label{#3}\\}%
%  \g@addto@macro\aligngroup{\aligneqs{#2}{#3}&\text{#2}&#1\label{#3}\\}%  ALTERNATE FORM
}
\makeatother
\allowdisplaybreaks
\begin{document}
\listofequations\vspace{140pt}
\InsertEquation{T(x) &= ae^{-\frac{(x-b)^2}{2c^2}}} {Model 1: Base formula}{eq:m1gauss}
With a blah-blah here,%
\InsertEquation{\frac{1}{2} < a &\leq 1}            {Model 1: Condition 1} {eq:m1va}
and a blah-blah there,%
\InsertEquation{b &= \SI{25}{\degreeCelsius}}       {Model 1: Condition 2} {eq:m1vb}
here a blah, there a blah,%
\InsertEquation{c &= \frac{5}{\sqrt{2 \ln{2a}}} > 0}{Model 1: Condition 3} {eq:m1vc}
everywhere a blah-blah.

\lipsum[1-2]Blah-blah occurs before the \texttt{align} is generated:
\GenerateAlign
In equation~\ref{eq:m1vb}...
\end{document}

enter image description here

第2页:

enter image description here

我在定义中提供了一个注释的替代形式\InsertEquation,可以用作 的替代形式\g@addto@macro\aligngroup{\aligneqs{#2}{#3}#1\label{#3}\\}。替代形式如下所示:

enter image description here

答案2

目前尚不清楚为什么这里需要延迟执行

\documentclass{article}

\usepackage{amsmath,siunitx}

\usepackage{tocloft}
\newcommand{\loename}{List of equations}
\newlistof{equations}{equ}{\loename}


\newcommand\InsertEquation[3]{%
\\%
#1\label{#3}%
\addcontentsline{equ}{equations}{\protect\numberline{\ref{#3}}{#2}}%
}
\def\firstequation{\expandafter\gobblenl}
\def\gobblenl\\{}
\begin{document}

\listofequations


\begin{align}
\firstequation
\InsertEquation{T(x) &= ae^{-\frac{(x-b)^2}{2c^2}}}{Model 1: Base formula}{eq:m1gauss}
\InsertEquation{\frac{1}{2} < a &\leq 1}{Model 1: Condition 1}{eq:m1va}
\InsertEquation{b &= \SI{25}{\degreeCelsius}}{Model 1: Condition 2}{eq:m1vb}
\InsertEquation{c &= \frac{5}{\sqrt{2 \ln{2a}}} > 0}{Model 1: Condition 3}{eq:m1vc}
\end{align}

\end{document}

相关内容