这个命令可以转换为环境吗?

这个命令可以转换为环境吗?

我有如下命令:

\newcommand{\Comment}[1]{&&&#1\tabularnewline\hline}

现在我想将其转换为如下环境:

\newsavebox{\tempDescription}
\newenvironment{Description}
{%
\begin{lrbox}{\tempDescription}%
\ignorespaces%
}
{%
\end{tempDescription}%
&&&\usebox{\tempDescription}\tabularnewline\hline%
}

完整代码如下:

\documentclass[dvips,dvipsnames,rgb,table]{book}

\usepackage[a4paper,hmargin=10mm,vmargin=40mm,showframe]{geometry}
\usepackage{longtable}
\usepackage{array}
\usepackage{calc}
\usepackage{lscape}
\setlength{\tabcolsep}{10pt}
\setlength{\arrayrulewidth}{1pt}
\newcounter{No}
\renewcommand{\theNo}{\arabic{No}}
\newenvironment{MyTable}[4]%
{%
    \newcolumntype{O}[1]%
    {%
        >{%
            \begin{minipage}%
            {%
                    ##1\linewidth-2\tabcolsep-1.5\arrayrulewidth%
            }%
            \vspace{\tabcolsep}%
         }%
        c%
        <{%
                \vspace{\tabcolsep}%
                \end{minipage}%
         }%
    }%
    \newcolumntype{I}[1]%
    {%
        >{%
            \begin{minipage}%
            {%
                    ##1\linewidth-2\tabcolsep-\arrayrulewidth%
            }%
            \vspace{\tabcolsep}%
         }%
        c%
        <{%
                \vspace{\tabcolsep}%
                \end{minipage}%
         }%
    }%
    \setcounter{No}{0}%comment out this if you want to continuous numbering for all tables.
    \begin{longtable}%
    {%
            |>{\stepcounter{No}\centering\scriptsize\theNo}O{#1}<{}%
            |>{\centering}I{#2}<{\input{\jobname.tmp}}%
            |>{\centering\lstinputlisting{\jobname.tmp}}I{#3}<{}%
            |>{\scriptsize}O{#4}<{}%
            |%
    }%
    \hline\ignorespaces%
}%
{%
    \end{longtable}%
}

\newcommand{\Comment}[1]{&&&#1\tabularnewline\hline}

\newsavebox{\tempDescription}
\newenvironment{Description}
{%
\begin{lrbox}{\tempDescription}%
\ignorespaces%
}
{%
\end{tempDescription}%
&&&\usebox{\tempDescription}\tabularnewline\hline%
}

\usepackage{listings}
\lstset{%
language={PSTricks},
breaklines=true,
basicstyle=\ttfamily\scriptsize,%
keywordstyle=\color{blue},
backgroundcolor=\color{yellow!30}%
}
\usepackage{fancyvrb}


\def\MyRow{%        
        \VerbatimEnvironment%
        \begin{VerbatimOut}{\jobname.tmp}%
}

\def\endMyRow{%
        \end{VerbatimOut}%      
}



\usepackage{pstricks,pst-node}
\newpsstyle{gridstyle}{%
gridwidth=0.4pt,%default: 0.8pt
gridcolor=Red!20,%default: black
griddots=0,%default: 0 
%
gridlabels=3pt,%default: 10pt
gridlabelcolor=Blue,%default: black
%
subgriddiv=5,%default: 5
subgridwidth=0.2pt,%default: 0.4pt
subgridcolor=Green!20,%default: gray
subgriddots=0%default: 0
}

\usepackage{lipsum}


\begin{document}
%\clearpage
%\pagestyle{empty}
%Landscape starts here.
%\begin{landscape}
\arrayrulecolor{Red}
\begin{MyTable}{0.05}{0.3}{0.3}{0.35}%
%=============
\begin{MyRow}
\pspicture*[showgrid](3,3)
\pnode(1,1){A}
\pnode(3,3){B}
\ncline{A}{B}
\endpspicture
\end{MyRow}
\Comment{\lipsum[1]}
%=============
\begin{MyRow}
\begin{pspicture}[showgrid](3,3)
\psframe*[linecolor=red!30](3,2)
\end{pspicture}
\end{MyRow}
\Comment{\lipsum[2]}
%=============
\begin{MyRow}
\pspicture[showgrid](3,3)
\psframe*[linecolor=green!30](3,2)
\endpspicture
\end{MyRow}
\Comment{\lipsum[3]}
%=============
\begin{MyRow}
\pspicture[showgrid](3,3)
\psframe*[linecolor=Yellow](3,2)
\endpspicture
\end{MyRow}
\Comment{%
\begin{equation}
\int_a^b f(x)\, \textrm{d}x=F(b)-F(a)
\end{equation}
is the fundamental theorem of calculus.
}
%=============
\begin{MyRow}
\pspicture[showgrid](3,3)
\psframe*[linecolor=Maroon!30](3,2)
\endpspicture
\end{MyRow}
\begin{Description}%{%
Today I ate burnt bread. It was so delicious.
\begin{equation}
\int_a^b f(x)\, \textrm{d}x=F(b)-F(a)
\end{equation}
is the fundamental theorem of calculus.
%}
\end{Description}
%=============
\end{MyTable}
%\end{landscape}
%Landscape stops here.
%\pagestyle{plain}
\end{document}

为什么无法转换?

答案1

快速回答:

\usepackage{environ}
\NewEnviron{Description}{%
  \expandafter\gdef\expandafter\gtemp\expandafter{%
    \expandafter&\expandafter&\expandafter&\BODY\tabularnewline\hline
  }%
  \aftergroup\gtemp
}

它不允许逐字文本,但该包cprotect可以修复这个问题。我第一次尝试直接接受逐字文本,但使用 lrbox 只允许单行框(不完全正确)。

我们使用 Will Robertson 的environ包来定义Description环境。它读取环境的全部内容(直到达到\end{Description})并将其存储在中\BODY。天真地,我们希望

\NewEnviron{Description}{%
  &&&\BODY\tabularnewline\hline}

但是这失败了:&&&\BODY\tabularnewline\hline在组内创建,整个过程的行为有点像{&&&\BODY...}而不是&&&\BODY...。我们想将&移出组。这可以使用\aftergroup原语来完成:{...\aftergroup\a}给出{...}\a,即\a在组完成后执行。

因此,我们将要执行的操作存储在命令中,\gtemp然后执行\aftergroup\gtemp。因此,你会认为正确的代码是

\NewEnviron{Description}{%
  \gdef\gtemp{%
    &&&\BODY\tabularnewline\hline
  }%
  \aftergroup\gtemp
}

但它是不是结束。\BODY当我们在组内时,它只是我们环境的主体。当我们尝试&&&\BODY\tabularnewline\hline在组外执行时,我们得到一个错误:\BODY没有定义。我们该怎么办?我们需要\BODY用它的替换扩张(定义)我们仍在组内。对于这种使用\expandafter,这非常实用,但使用起来很麻烦。它告诉 TeX“看到下一个标记了吗?好吧……等等,先执行(扩展)下一个”。典型的构造是\expandafter\a\expandafter\b\expandafter\c\expandafter\d\e。第一个\expandafter读取\a,并扩展下一个标记\expandafter。第二个\expandafter看到\b,但首先扩展\expandafter,等等。最后,\e首先扩展,然后是,,,\a。(各种标记不会重新排序:只有它们扩展的方式会发生变化。)\b\c\d

因此,在我们的最终代码中,我在这里重复一遍,

\usepackage{environ}
\NewEnviron{Description}{%
  \expandafter\gdef\expandafter\gtemp\expandafter{%
    \expandafter&\expandafter&\expandafter&\BODY\tabularnewline\hline
  }%
  \aftergroup\gtemp
}

我们首先展开\BODY,然后\gdef\gtemp{&&&身体\tabularnewline\hline}, 在哪里身体是环境的真实内容(\BODY已展开)。最后,\aftergroup\gtemp上面的解释会将其放在表格流中的正确位置。

答案2

由于 TeX 解析参数以进行对齐的方式(这是表格的基础技术),您所做的工作不起作用。在决定将什么放入表格单元格时,TeX 会读取一个启用宏扩展的标记,检查是否存在特殊情况,例如\span,然后扫描不启用宏扩展的文本,直到下一个&\cr标记。它找到的内容会放入表格单元格,然后以通常的方式进行处理,包括宏扩展和所有内容。

您的问题是,\begin{Description}在执行 之前会进行各种设置\Description,特别是\Description在 TeX 遇到由扩展 产生的第一个不可扩展标记之前不会进行扩展\begin。因此 TeX 看不到&其中的标记,并假设它们全部进入单个表格单元格。

相关内容