我有一个自定义环境,用于处理指定为的代码接口声明:
\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>
,但这似乎不起作用,因为\appto
ed 命令的使用在处理程序中被急切扩展\begin{decl}
,而附加的字符串并没有被使用。
答案1
有没有标准的方法?嗯,这是其中一种方法。
该包允许我们多次使用环境的environ
收集。\BODY
我们用了两次:
- 构建
\@paramlist
包含两个参数的\param
。这将在未设置类型的框内“执行”。 - 原来的定义
\param
实际上\BODY
是在description
环境中排版的。
笔记
- 的初始定义
\@paramlist
是\@gobbletwo
,其唯一目的是吞噬第一个逗号和空格。根据您对此列表的输出,您可能会更改整个过程和 的定义decl@param
。 当
\@paramlist
使用时,它后面直接跟着两个\@empty
(定义为)\def\@empty{}
。如果\param
环境中没有出现,这将停止\@paramlist
(即\@gobbletwo
)抓取)
,更重要的是\begin
。
(感谢大卫·卡莱尔谁使用过这个他的(已删除)答案。参考
- 为什么 \@gobble 需要一个参数
- 何时使用 \LetLtxMacro?(如果
\param
包含可选参数或通过定义xparse
) - \setbox 与 \sbox 和 \savebox - 我需要了解哪些区别?
代码
\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}