延迟 \begin handler 中出现的命令扩展,直到 \end handler 执行

延迟 \begin handler 中出现的命令扩展,直到 \end handler 执行

我有一个自定义环境,用于处理指定为的代码接口声明:

\begin{decl}{FOO}
\param{in}{bar} the bar input parameter
\param{out}{baz} the baz input parameter
\end{decl}

这被我的包排版为嵌套列表(注意:现实要复杂得多,但这主要抓住了想法)。

\newrobustcmd*{\param}[2]{
  \item[#1 #2]
}

\newenvironment{decl}[1]{
  \begin{enumerate}
  \item #1(<param names here>)
    \begin{description}
}{
    \end{description}
  \end{enumerate}
}

我的问题是我需要积累名称\param,然后在\end{decl}处理程序中我需要将它们注入标记为的位置<param names here>。不幸的是,我在生成该项目时不知道要注入的列表。

有没有规范的方法来做到这一点?

我考虑etoolbox在处理 s 时使用列表功能构建内部列表\param,然后enumerate\end{decl}处理程序中生成整个结构,但我不知道如何在不使用 的情况下捕获 的“描述”\parbox以供以后使用,据我所知,这需要在项目之间进行段落分隔,而源中不存在这种情况。我可以引入第三个参数,以便将描述作为第三个参数处理,但这需要对 .tex 源库进行相当大的更改。\param\par\param\param

\appto我确实更喜欢用命令代替的方法<param names here>,但这似乎不起作用,因为\apptoed 命令的使用在处理程序中被急切扩展\begin{decl},而附加的字符串并没有被使用。

答案1

有没有标准的方法?嗯,这是其中一种方法。

该包允许我们多次使用环境的environ收集。\BODY

我们用了两次:

  1. 构建\@paramlist包含两个参数的\param。这将在未设置类型的框内“执行”。
  2. 原来的定义\param实际上\BODY是在description环境中排版的。

笔记

代码

\documentclass{article}
\usepackage{etoolbox,environ}

\makeatletter
\newrobustcmd*\orig@param[2]{\item[{#1 #2}]}%
\newrobustcmd*\decl@param[2]{\gappto\@paramlist{,\ #1 #2}}% needs to be global
\NewEnviron{decl}[1]{%
  \def\@paramlist{\@gobbletwo}% \@gobbletwo will remove the first comma and space
  \let\param\decl@param
  \sbox0{\BODY}% will not be typeset but "executed"
  \let\param\orig@param
  \begin{enumerate}
  \item #1 (\@paramlist\@empty\@empty)
    \begin{description}
        \BODY
    \end{description}
  \end{enumerate}
}
\makeatother
\begin{document}
\begin{decl}{Environment contains}
\param{Foo}{Bar} Foobar
\param{Ding}{Dong} Dingenskirchen
\param{La}{TeX} LaTeX
\end{decl}
\end{document}

输出

在此处输入图片描述

答案2

\newenvironment只要您愿意运行文档两次,就可以使用而不加载辅助包。无论如何,您必须运行两次才能正确获取引用(部分等)。感谢egreg他的评论。

\documentclass{article}
\makeatletter
\newcount\paramenvcount
\newcommand*\addparam[2]{%
  \expandafter\let\expandafter\tempa\csname paramlist/#1\endcsname
  \ifdefined\tempa
    \ifx\tempa\relax\def\tempa{}\fi
  \else
    \def\tempa{}%
  \fi
  \expandafter\protected@xdef\csname paramlist/#1\endcsname{%
    \tempa\ifx\tempa\empty\else, \fi#2%
  }%
}
\newcommand*{\param}[1]{\@testopt{\param@a{#1}}\space}
\def\param@a#1[#2]#3{%
  \immediate\write\@auxout{%
    \noexpand\addparam{\the\paramenvcount}{\unexpanded{#1#2#3}}%
  }%
  \item[#1#2#3]%
}
\newenvironment{decl}[1]{%
  \global\advance\paramenvcount\@ne
  \begin{enumerate}%
  \item #1 (\@nameuse{paramlist/\the\paramenvcount})
  \begin{description}%
}{%
  \end{description}%
  \end{enumerate}%
}
\makeatother

% Tests:
\begin{document}
\begin{decl}{Environment 1 contains}
\param{Foo}{Bar} Foobar
\param{Ding}{Dong} Dingenskirchen
\param{La}[]{TeX} \LaTeX
\end{decl}

\begin{decl}{Environment 2 contains}
\param{Foo2}[*]{Bar2} Foobar2
\param{Ding2}[*]{Dong2} Dingenskirchen2
\param{La}[]{TeX2} \LaTeX2
\end{decl}
\end{document}

在此处输入图片描述

在您的方法中, 内\item始终只有一个。我发现结果相当无趣。我会使用以下方案。\enumerate\decl

\documentclass{article}
\makeatletter
\newcount\entryenvcount
\newcommand*\gettempa[1]{%
  \begingroup\expandafter\endgroup\expandafter
  \let\expandafter\tempa\csname paramlist/#1\endcsname
}
\newcommand*\addparam[2]{%
  \gettempa{#1}%
  \ifdefined\tempa\else\def\tempa{}\fi
  \expandafter\protected@xdef\csname paramlist/#1\endcsname{%
    \tempa\ifx\tempa\empty\else, \fi#2%
  }%
}
\newenvironment{decl}[1]{%
  \global\advance\entryenvcount\@ne
  \def\entry{\@testopt\entry@a{}}%
  \def\entry@a[##1]{%
    \immediate\write\@auxout{%
      \noexpand\addparam{\the\entryenvcount}{\unexpanded{##1}}%
    }%
    \labelwidth=-\if\relax\detokenize{##1}\relax3.25\else5\fi mm\relax
    \item[##1]%
  }%
  \gettempa{\the\entryenvcount}%
  \protected@xdef\tempa{%
    \ifdefined\tempa\ifx\tempa\empty\else(\tempa)\fi\fi
  }%
  \noindent\hbox to 5mm{\the\entryenvcount.\hfil}#1~\tempa
  \begin{description}%
}{%
  \end{description}%
}
\makeatother

% Tests:
\begin{document}
\begin{decl}{Environment 1 contains}
\entry[Foo, Bar] Foobar
\entry[Ding, Dong] Dingdong
\entry[La,TeX] \LaTeX
\end{decl}

\begin{decl}{Environment 2 contains}
\entry[Foo2, Bar2] Foobar2
\entry[Ding2, Dong2] Dingdong2
\entry[La,TeX2] \LaTeX2
\end{decl}

\begin{decl}{Environment 3 contains no tags}
\entry Foobar3
\entry Dingdong3
\entry \LaTeX3
\end{decl}
\end{document}

在此处输入图片描述

相关内容