我一直在致力于实现一个环境(永不嵌套)和一个命令,用于保存文档的不同部分,并在稍后使用列表expl3
和在其中使用它们xparse
。到目前为止,一切顺利,运行正常,但是,在分析文件时,.fls
我注意到有些不对劲。当编写辅助文件然后从列表中调用它们时,这会在内存中加载两次。我拥有的代码(MWE)是这样的:
% arara: pdflatex : {action: nonstopmode, options: "-recorder"}
\documentclass{article}
\usepackage{environ,xparse,fvextra,xcolor}%
\ExplSyntaxOn
\cs_new:Npn \elementin #1
{
\seq_count:c {l_savecontent_content_#1_seq}%
}
\cs_new:Npn \clearlist #1
{
\seq_clear_new:c {l_savecontent_content_#1_seq}%
}
\NewDocumentCommand{\addcontent}{m +m}
{
\savecontent_add_content:nn { #1 } { #2 }
}
\DeclareExpandableDocumentCommand{\usecontent}{O{1}m}
{
\savecontent_use_content:nn { #1 } { #2 }
}
\cs_new_protected:Npn \savecontent_add_content:nn #1 #2
{
\seq_if_exist:cF { l_savecontent_content_#1_seq }
{ \seq_new:c { l_savecontent_content_#1_seq } }
\__savecontent_add_content:nn { #1 } { #2 }
}
\cs_new_protected:Npn \__savecontent_add_content:nn #1 #2
{
\tl_map_inline:nn { #2 }
{
\seq_gput_right:cn { l_savecontent_content_#1_seq } { ##1 }
}
}
\cs_new:Npn \savecontent_use_content:nn #1 #2
{
\seq_item:cn { l_savecontent_content_#2_seq } { #1 }
}
\keys_define:nn { scontent }
{
save-cmd .tl_set:N = \l_scontent_cmd_save_tl,%
show-cmd .bool_set:N = \l_scontent_cmd_show_tl,%
save-env .tl_set:N = \l_scontent_env_save_tl,%
show-env .bool_set:N = \l_scontent_env_show_tl,%
show-inf .bool_set:N = \l_scontent_inf_show_tl,%
name-tmp .tl_set:N = \l_scontent_tmp_name_tl,%
temp-ext .tl_set:N = \l_scontent_ext_temp_tl,%
body-env .bool_set:N = \l_scontent_env_body_tl,%
verb .meta:n = { body-env = false },%
show-all .meta:n = { show-env = true , show-cmd = true },%
}
\keys_set:nn { scontent }
{
save-cmd = content,%
show-cmd = false,%
save-env = content,%
show-env = false,%
name-tmp = \jobname,%
temp-ext = tsc,%
show-inf = false,%
body-env = true,%
}
\NewDocumentCommand{\Setscontent}{ +m }
{
\keys_set:nn { scontent } {#1}
}
\newrobustcmd{\envtolist}[1]{\addcontent{ \l_scontent_env_save_tl }{{#1}}}
\newcounter{outNr}
\tl_new:N \filetolist
\NewEnviron{SAVEcontent}[1]{}
\NewDocumentEnvironment{scontent}{ !o }
{
\group_begin:
\IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
\IfBooleanTF { \l_scontent_env_body_tl } { \SAVEcontent{#1} }
{ \stepcounter{outNr} \VerbatimOut{\l_scontent_tmp_name_tl-\theoutNr.\l_scontent_ext_temp_tl}}
}{
\IfBooleanTF { \l_scontent_env_body_tl }
{\endSAVEcontent\expandafter\envtolist\expandafter{\BODY}}
{\endVerbatimOut
\tl_put_right:Nx \filetolist { {\envtolist { \exp_not:N \input {
\exp_after:wN \l_scontent_tmp_name_tl-\theoutNr.\l_scontent_ext_temp_tl } } } }
\filetolist
}
\IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
\IfBooleanT { \l_scontent_inf_show_tl }
{\marginpar{\scriptsize\ttfamily saved ~ in ~ \l_scontent_env_save_tl, ~ index ~ \elementin{\l_scontent_env_save_tl}}}
\group_end:
}
\NewDocumentCommand{\Scontent}{!o +m}
{
\group_begin:
\IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
\addcontent{ \l_scontent_cmd_save_tl }{{#2}} % pass direct to list
\IfBooleanT { \l_scontent_cmd_show_tl } { \usecontent[-1]{ \l_scontent_cmd_save_tl} }
\IfBooleanT { \l_scontent_inf_show_tl }
{\marginpar{\scriptsize\ttfamily saved ~ in ~ \l_scontent_cmd_save_tl, ~ index ~ \elementin{\l_scontent_cmd_save_tl}}}
\group_end:
}
\ExplSyntaxOff
\setlength{\parindent}{0pt}
\pagestyle{empty}
\begin{document}
\Setscontent{save-env=test-env, save-cmd=test-cmd}
\section{Test scontent env OK}
The following blocks of text will be stored directly in list or in external files and
then referenced using lists, not shown directly.\par
\begin{scontent}[show-inf]
\textcolor{red}{First Text}....use environ
\end{scontent}
\begin{scontent}[verb]
\textcolor{green}{Second Text}...save in \verb+\jobname-1.tsc+
\end{scontent}
\begin{scontent}[verb]
\textcolor{blue}{Third Text}...save in \verb+\jobname-2.tsc+
\end{scontent}
Now we can see that the number of items saved in the list is \elementin{test-env} and
we can show them in reverse order whit \verb+\usecontent[...]{test-env}+:\par
\usecontent[3]{test-env}\par\vspace{0.5cm}
\usecontent[2]{test-env}\par\vspace{0.5cm}
\usecontent[1]{test-env}\par\vspace{0.5cm}
\section{Test Scontent comand OK}
\Scontent[show-inf]{using a \textcolor{orange}{\texttt{\textbackslash Scontent}}\ command version}
No \verb+\verb+ supported by environ :( [no problem, use env for this] :)\par
\usecontent{test-cmd}
\end{document}
该文件的输出.fls
是:
$ cat forum.fls | grep \.tsc
OUTPUT forum-1.tsc
OUTPUT forum-2.tsc
INPUT forum-2.tsc
INPUT forum-2.tsc
INPUT forum-1.tsc
INPUT forum-1.tsc
并应出去:
OUTPUT forum-1.tsc
OUTPUT forum-2.tsc
INPUT forum-1.tsc
INPUT forum-2.tsc
也就是说,执行时应该\usecontent
只显示,我认为问题出在或 的行上,保存时会扩展。下图显示了它的工作原理:INPUT
.fls
\filetolist
\addtolist
\input
我已阅读文档,但其水平远高于我的水平,我仍无法找到问题的解决方案。Saludos
PS:欢迎评论以改进代码
答案1
您在 fls 文件(来自)选项中观察到的现象-recorder
可能与您的代码无关。它是 LaTeX在表单\input
中使用时产生的产物。\input{file}
考虑一下
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{\jobname-test}
This is a test file
\end{filecontents}
\begin{filecontents}{\jobname-test2}
This is another test file
\end{filecontents}
\begin{document}
\input{\jobname-test}
\input \jobname-test2
\end{document}
并用 编译它pdflatex -recorder
。这将创建一个 fls 文件,由于 filecontents 的原因,将有对测试文件的多个引用,但提取相关行我得到了这个
....
INPUT filename.aux
INPUT filename.aux
OUTPUT filename.aux
INPUT filename-test.tex
INPUT filename-test.tex
INPUT filename-test2.tex
OUTPUT filename.pdf
....
如您所见,\input filename
表单仅创建一个条目,但\input{filename}
创建了两个。
$ latexdef input
\input:
macro:->\@ifnextchar \bgroup \@iinput \@@input
$ latexdef @iinput
\@iinput:
macro:#1->\InputIfFileExists {#1}{}{\filename@parse {#1}\edef \reserved@a {\noexpand \@missingfileerror {\filename@area \filename@base }{\ifx \filename@ext \relax tex\else \filename@ext \fi }}\reserved@a }
将\InputIfFileExits
打开文件进行两次读取,第一次将检查是否存在。
另一方面\@@input
是 TeX 的原语,它当然只打开一次。