我想存储环境的内容并将它们添加到宏或命令中,以便轻松检索它们,但我不想使用 collect 包。还有其他选择吗?
\documentclass{article}
\usepackage{environ}
\usepackage{blindtext}
\NewEnviron{env}{
\global\let\content\BODY
%i want to add content to running list and later get whole contents
}
\begin{document}
\begin{env}
text text text\\
\end{env}
\blindtext
\begin{env}
moretext moretext more text\\
\end{env}
\end{document}
答案1
您可以按“名称”打印已保存的环境,也可以打印全部已保存的环境。
由于使用了,这需要两次运行(当保存的环境发生变化时)\label
。
更新
由于etex
现在不鼓励使用方法,因此这里使用 重新实现expl3
。
\documentclass{article}
\usepackage{refcount}
\ExplSyntaxOn
\newcounter{savedenv}
\seq_new:N \g_ephraim_savedenv_seq
\NewDocumentEnvironment{savedenv}{ o +b }
{
\refstepcounter{savedenv}
\IfValueT{#1}{\label{savedenv@#1}}
\seq_gput_right:Nn \g_ephraim_savedenv_seq { #2 }
}{}
\NewDocumentCommand{\printsaved}{m}
{% #1 is a list of labels
\clist_map_inline:nn { #1 }
{
\seq_item:Nn \g_ephraim_savedenv_seq { \getrefnumber{savedenv@##1} }
\par
}
}
\NewDocumentCommand{\printallsaved}{}
{
\seq_use:Nn \g_ephraim_savedenv_seq { \par }
}
\ExplSyntaxOff
\begin{document}
\begin{savedenv}[a]
Something for a
\end{savedenv}
\begin{savedenv}[b]
Something for b
\end{savedenv}
\begin{savedenv}
Something with no label
\end{savedenv}
\textbf{Let's print them}
This is a: \printsaved{a}
This is b: \printsaved{b}
\textbf{Let's print them in different order}
\printsaved{b,a}
\textbf{Print all of them}
\printallsaved
\end{document}
原始代码
\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}[a]
Something for a
\end{savedenv}
\begin{savedenv}[b]
Something for b
\end{savedenv}
\begin{savedenv}
Something with no label
\end{savedenv}
\textbf{Let's print them}
This is a: \printsaved{a}
This is b: \printsaved{b}
\textbf{Print all of them}
\printallsaved
\end{document}
您最多可以保存 1000 个环境,但您可以用明显的方式更改该数字。不要尝试将数字设置为超过 30000。
答案2
我建议使用newenviron
包而不是environ
,因为它定义了一个\envnamebody
命令。
注意:不要调用你的环境env
,因为它会与\envbody
始终由 为任何环境定义的隐式命令发生冲突newenviron
。
更改后,可以使用etoolbox
-list 命令\listgadd
等,将forlistloop
当前内容添加到列表中并稍后进行处理,例如打印它。
你需要一个‘打印’命令,我将其命名为\showlist
。
内容在环境代码的末尾粘合在一起,中间没有任何空格。
编辑版本——将“任意(?)”文本粘合在一起
\documentclass{article}
\usepackage{tcolorbox}
\usepackage{newenviron}
\usepackage{blindtext}
\usepackage{etoolbox}
\def\mylist{}%
\listadd{\mylist}{}% Initialize list
\newrobustcmd{\myexpandingcommand}[1]{%
\listgadd{\mylist}{#1}%
}%
\newenviron{content}{%
}{%
\noindent\textbf{\LARGE \textcolor{blue}{Environment content}} % Remove later on!
\noindent\envbody%
\expandafter\myexpandingcommand\expandafter{\envbody}%
\endgraf\bigskip\bigskip% Can be removed
}%
% Macro showing the current list element%
\newrobustcmd{\showlist}[1]{%
#1%
}%
\begin{document}
\begin{content} % Store some content%
\blindtext%
\end{content}
\noindent\textbf{\LARGE \textcolor{green}{Text content outside of environment}} % Can be removed, just for diagnosis/test
\noindent\blindtext
\endgraf\bigskip
\begin{content}
\textbf{\textcolor{red}{Even more text and now even some math: \huge \(\displaystyle\int\limits^{b}_{a} f(x) dx\)}}%
\end{content}
\begin{center}
\begin{tcolorbox}[width=0.8\textwidth,title={Now the combined content of the list}]
\forlistloop{\showlist}{\mylist}%
\end{tcolorbox}%
\end{center}
\end{document}
答案3
我把这个答案留在这里,因为它们对创建这个scontents
包很有启发。有了这个包,你很容易就能做你想做的事。所有内容都存储在内存中,包括逐字内容。如果你愿意,你也可以使用键将内容保存在外部文件中write-env=file.tex
。我总是倾向于将内容存储在内存中:)
\documentclass{article}
\usepackage{scontents}
\pagestyle{empty}
\begin{document}
\begin{scontents}[store-env=main]
Something for main A.
\end{scontents}
\begin{scontents}[store-env=main]
Something for \verb|main B|.
\end{scontents}
\begin{scontents}[store-env=other]
Something for \verb|other|.
\end{scontents}
\textbf{Let's print them}
This is first stored in main: \getstored[1]{main}\par
This is second stored in main: \getstored[2]{main}\par
This is stored in other: \getstored[1]{other}
\textbf{Print all of stored in main}\par
\foreachsc[sep={\\[10pt]}]{main}
\end{document}
问候语
答案4
这个答案涉及收集和存储环境的内容逐字。(一些优点包括在检索时使用等于 catcode 的 catcode 执行内容,这可以使用例如来完成\scantokens
),否则您可能希望将选定的内容传递给 Python 或类似的东西)
其他选择:
- 使用
\VerbatimOut
fromfancyvrb
来逐字存储内容(需要外部文件)。 - LuaTeX 专用解决方案在 LuaLaTeX 中,如何将环境的内容逐字传递给 Lua?
- 网站上其他用户编写的宏
- 定义您自己的环境/命令来手动操作 catcodes
\endlinechar
。
方法 | 标签 | 空间 | 新队 | 最后换行符 | 信件 | 其他的 |
---|---|---|---|---|---|---|
+v xparse 中的参数类型(*) |
不起作用(链接包含解决方法的补丁) | 空间猫代码 | \ExplSyntax - Off : 字符 13 猫其他,\ExplSyntax - On :第一个字符与\endlinechar (固有的 TeX 限制,无法修复)相同,其余同上 |
用户指定 | 其他猫 | 其他猫 |
\collectverb 和\Collectverb (*) |
\ExplSyntax - On :忽略;\ExplSyntax - Off :行首:删除,否则:用空格分隔符 catcode |
活跃空间 | \ExplSyntax - On :活动空间,\ExplSyntax - Off :活动字符 13 |
用户指定 | 信猫 | 其他猫 |
\collectverb* 和\Collectverb* (*) |
\ExplSyntax - On :忽略;\ExplSyntax - Off :行首:删除,否则:与空格 → 相同 |
与其他猫有空间 | \ExplSyntax - On :空格,\ExplSyntax - Off :活动字符 13 |
用户指定 | 信猫 | 其他猫 |
\collect -verbenv 和\Collect - verbenv (\ExplSyntaxOn 删除环境中的第一行) |
活动标签(字符 9) | 活跃空间 | 活动换行符(字符 13) | 用户指定 | 信猫 | 其他猫 |
file - contents -defmacro 环境 |
\FCDtab 由-控制tomacro ,默认:与空格相同 |
主动,默认展开到太空(太空猫) | 活动,字符 13,默认扩展为\par |
始终存在 | 信猫 | 其他猫 |
scontents 内部宏 |
其他猫 | 其他猫 | 字符10猫其他 | 剥离 | 信猫 | 其他猫 |
(*): 不是一个真正的环境
评论:
- 对于以
{}
:分隔的,{}
可以使用它作为分隔符,只要内部{}
是平衡的。 - 该线
\begin{...}
通常\end{...}
必须在单独的线上。 - 大多数情况下,如果作者没有对制表符/换行符进行任何特殊处理,则其行为是“实现定义的默认行为”。 (可以通过重新定义
\endlinechar
或手动设置其 catcode 等来更改) - 通过重新定义活动角色的含义,可以改变其扩展内容。
scontents
宏是内部方法,随时都有可能断裂。- 正如文档中提到的,大多数情况下它可以嵌套。
\getstored
不可扩展。- 但是有一个内部方法(见下面的示例代码)
\begin{scontents}[store-env=test]
\a test & test %comment
second line
third line
\end{scontents}
\ExplSyntaxOn
\tl_new:N \my__a
are stored as characters.
\tl_set:Nx \my__a { \__scontents_getfrom_seq:nn {1} {test} }
\tl_remove_once:NV \my__a \c__scontents_hidden_space_str
\tl_analysis_show:N \my__a
\ExplSyntaxOff
- 包定义的环境
environ
不会逐字存储内容。 - 包定义的环境
newenviron
不会逐字存储内容。(加上我在评论中提到的另一个问题)收集环境内容并存储以供日后检索)