我有以下内容,适用于一个 toks 块,即 \savedenvtoks,但我想创建更多 toks 块,并且我希望 \savedenv 采取一个参数来指示要添加到哪个 toks 块,并且我希望 \printallsaved 命令采取一个参数来指示从哪个 tok 块打印。
\documentclass{article}
\usepackage{etex,environ,refcount}
\globtoksblk\savedenvtoks{1000}
\newcounter{savedenvcount}
\NewEnviron{savedenv}[1][]{%
\refstepcounter{savedenvcount}%
\if\relax\detokenize{#1}\relax
\else
\label{#1}%
\fi
\global\toks\numexpr\savedenvtoks+\value{savedenvcount}\relax=\expandafter{\BODY}%
}
\toks\savedenvtoks={??}
\newcommand{\printsaved}[1]{%
\the\toks\numexpr\savedenvtoks+\getrefnumber{#1}\relax
}
\makeatletter
\newcommand{\printallsaved}{%
\@tempcnta=\z@
\loop
\ifnum\@tempcnta<\value{savedenvcount}
\advance\@tempcnta\@ne
\the\toks\numexpr\savedenvtoks+\@tempcnta\relax\par
\repeat
}
\makeatother
\begin{document}
\begin{savedenv}
Something for a
\end{savedenv}
\begin{savedenv}
Something for b
\end{savedenv}
\begin{savedenv}
Something with no label
\end{savedenv}
\textbf{Print all of them}
\printallsaved
\end{document}
答案1
我们可以抽象出前面答案中的想法:
\documentclass{article}
\usepackage{etex,environ,refcount}
\makeatletter
\newcommand{\declaresaveclass}[2][1000]{%
\expandafter\globtoksblk\csname ncory@class@#2\endcsname{#1}%
\global\expandafter\toks\csname ncory@class@#2\endcsname{??}%
\newcounter{ncory@class@count@#2}%
\@namedef{thencory@class@count@#2}{%
\number\csname ncory@class@#2\endcsname+\arabic{ncory@class@count@#2}\relax
}%
}
\NewEnviron{savedenv}[2][]{%
\refstepcounter{ncory@class@count@#2}%
\if\relax\detokenize{#1}\relax
\else
\label{#1}%
\fi
\global\toks\ncory@compute@v{#2}=\expandafter{\BODY}%
}
\newcommand\ncory@compute@v[1]{%
\numexpr\csname ncory@class@#1\endcsname+\value{ncory@class@count@#1}\relax
}
\newcommand\ncory@compute@r[2]{%
\numexpr\csname ncory@class@#2\endcsname+\getrefnumber{#1}\relax
}
\newcommand{\printsaved}[2]{%
\toks0={??}%
\the\toks\numexpr\getrefnumber{#1}\relax\par
}
\newcommand{\printallsaved}[1]{%
\@tempcnta=\z@
\loop
\ifnum\@tempcnta<\value{ncory@class@count@#1}
\advance\@tempcnta\@ne
\the\toks\numexpr\csname ncory@class@#1\endcsname+\@tempcnta\relax\par
\repeat
}
\makeatother
\declaresaveclass{ONE}
\declaresaveclass[500]{TWO} % less registers for this class
\begin{document}
\begin{savedenv}[a]{ONE}
Something for a/ONE
\end{savedenv}
\begin{savedenv}[b]{TWO}
Something for b/TWO
\end{savedenv}
\begin{savedenv}{ONE}
Something with no label
\end{savedenv}
\textbf{Print all of them}
\textbf{ONE:}
\printallsaved{ONE}
\textbf{TWO:}
\printallsaved{TWO}
\textbf{Print by name}
\printsaved{a}
\printsaved{b}
\end{document}
您声明一个新的保存类,可选择调整保留寄存器的数量。然后,您可以打印类中的所有寄存器,也可以按名称打印其中任何一个。按名称打印需要运行两次 LaTeX(如果标签发生变化),因为它使用\label
-\ref
机制。
如果某个类的允许寄存器范围溢出,我们可以添加错误检查,但保留 1000 个寄存器应该已经相当安全了。