考虑以下代码:
\documentclass{book}
\usepackage{pgffor}
\begin{document}
\newcommand\containers{
\cont{aaa{\bf don't xstring me}aaa}
\cont{bbb\large bbb}
\containerssomemore{}
\cont{cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccI'm very long. don't \textbf{mbox} me. I'm going to be in very odd text widths etccccccccccccccccccccccc}
\cont{last one(\mbox{ddddd})}
}
\newcommand\containerssomemore{
\cont{yea here i am}
\cont{and me too}
}
\newcount\cntlines
\newcount\cntline
\newcommand\cont[1]{%
\advance\cntline by 1\relax%
\ifnum\cntline=\cntlines%
#1%
\fi%
}
\newcommand\passover[2]{%
\cntlines=#1\relax\cntline=0\relax%
#1
#2%
}
\foreach\idx in {6, 5, ..., 1}{%
\idx\footnote{\passover{\idx}{\containers}}
}
\end{document}
可以看出,代码以相反的顺序生成了 6 行脚注。我知道有更好的方法来生成此输出。这只是我需要对作为输入的文本行进行的一些(不太简单的)处理的示例。
但是,当我确实有包含在这些容器中的文本时,这很好。但我的实际输入文本将有所不同。它包含分隔符,如以下实现所示:
\documentclass{book}
\usepackage{pgffor}
\begin{document}
\newcommand\separators{%
aaa{\bf don't xstring me}aaa
\sep{}bbb\large bbb
\separatorssomemore{}
\sep{}cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccI'm very long. don't \textbf{mbox} me. I'm going to be in very odd text widths etccccccccccccccccccccccc
\sep{}last one(\mbox{ddddd})
\seperatorsevenmore{}
}
\newcommand\separatorssomemore{
\sep{}yea here i am
\sep{}and me too
}
\newcommand\seperatorsevenmore{
\sep{}another one
}
\newcount\cntlines
\newcount\cntline
\newsavebox\voidbox
\newcount\inbox \inbox=0\relax
\newcommand\sep{%
\global\advance\cntline by 1\relax%
\ifnum\cntline=\cntlines%
\end{lrbox}%
\fi%
\ifnum\cntline>\cntlines\ifnum\inbox=0\relax%
\begin{lrbox}{\voidbox}\inbox=1\relax%
\fi\fi%
}
\newcommand\passsep[2]{%
\cntlines=#1\relax\cntline=0\relax%
#1
\begin{lrbox}{\voidbox}\inbox=1\relax\sep{}#2\sep{}\end{lrbox}%
}
\foreach\idx in {6, 5, ..., 1}{%
\idx\footnote{\passsep{\idx}{\separators}}
}
\end{document}
从中可以看出,结果几乎相同(留出空白处的某些差异 - 这将很容易修复)。
但是第二个示例的主要缺点是我没有跳过不需要的行,而是将它们全部插入到一个框中。当有 6 行时不会注意到这一点,但我的实际代码有几千行,因此时间差异变得非常明显(以分钟为单位)。
我实际上需要一种方法来使文本的部分内容无效/忽略/跳过,同时仍在其中运行一些选定的宏。我相信我需要某种方法来预先扩展输入宏,例如通过某种方式进行替换,这样最终我会得到类似于容器宏的东西,然后才真正“运行”它。
我尝试过这种方法:
\documentclass{book}
\usepackage{pgffor}
\usepackage{environ}
\begin{document}
\newcommand\separators{%
aaa{\bf don't xstring me}aaa
\sep{}bbbbbb
\separatorssomemore{}
\sep{}cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccI'm very long. don't mbox me. I'm going to be in very odd text widths etccccccccccccccccccccccc
\sep{}last one(ddddd)
}
\newcommand\separatorssomemore{
\sep{}yea here i am
\sep{}and me too
}
\newcount\cntlines
\newcount\cntline
\NewEnviron{tocont}{%
\global\advance\cntline by 1\relax%
\ifnum\cntline=\cntlines%
\BODY%
\fi%
}
\newcommand\sep{%
\end{tocont}\begin{tocont}%
}
\newcommand\passenv[2]{%
\cntlines=#1\relax\cntline=0\relax%
\begin{tocont}#2\end{tocont}%
}
\foreach\idx in {6, 5, ..., 1}{%
\idx\footnote{\passenv{\idx}{\separators}}
}
\end{document}
但是它编译失败了,而且它太简单了以至于难以置信......
有人可以提出一个想法吗?
编辑:我在上面示例中的行中添加了一些属性,以强调它们可能包含脚注中允许的任何设计相关的宏。
我需要的是一种仅扩展\sep{}
宏和以 开头的宏的方法\seperators
(如我的示例:所有添加到文本行列表的宏都被称为\seperators<something>
)。
\sep{}
我想从一个宏“跳”到下一个宏(要么\seperators{}
直接包含在宏中,要么在这样的子宏中\seperators...
)。假设,如果这简化了,我只有一个间接级别。也就是说,一个子宏\seperators...
不会调用另一个子宏\seperators...
,但它可能会使用其他宏(\textbf
、\mbox
以及您能想到的任何其他宏),当然还有\sep{}
。
宏\sep{}
决定是否忽略所有文本直到下一个文本,或者展开并输出它。就像中间的文本被括在\cont{}
上面的 a 中一样。
如图所示,我可以通过将内容转储到虚拟框中来实现。但是有没有一种框可以告诉 TeX“不要浪费时间组织我。只要将内容转储出来,一切都会好起来”?我想这应该相当于跳过它。
或者,一种方法是采用一个宏并基于它“创建”另一个宏,一些使用原始宏代码的“函数”,只需“替换”“ ”}\cont{
而不是每个“ \sep{}
”?在这种情况下,我需要 2 次传递 - 一次扩展所有“ \seperators...{}
”行,第二次执行提到的字符串操作。然后我只需将结果作为宏“运行”即可定期扩展。
另一项编辑:事实证明我不需要在里面包含附加选项。也就是说,我只需要直接在宏中\seperators...
处理原始命令。\sep{}
这是否可以解决该问题?