创建令牌块来保存环境内容并稍后从中打印

创建令牌块来保存环境内容并稍后从中打印

我有以下内容,适用于一个 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 个寄存器应该已经相当安全了。

相关内容