我正在使用宏的修改来使用expl3
和保存到列表中xparse
。我已经设法创建了一个小的接口类型[key = val]
,并且使用environ
包我已经能够实现我的目标。问题是列表(如environ
)不支持类型的内容verbatim
,显然唯一的选择是编写辅助文件(.tsc
)然后使用\input{file-\tmpNr.tsc}
解决问题的什么。这就是我被困住的地方,我可以生成临时文件并将其添加到列表中\envtolist{\input{file-\tmpNr.tsc}}
,但在列表中,\tmpNr
每次\usecontent[...]{...}
使用该命令时它的值都会增加。
我只想在记录时记录当前值,并且将来不会修改它。我拥有的代码如下:
% MWE forum new
\documentclass{article}
\usepackage{environ,etoolbox,xparse,fvextra}%
% Definitions
\ExplSyntaxOn
% \elementin{listname} number of elements in listname
\cs_new:Npn \elementin #1
{%
\seq_count:c {l_savecontent_content_#1_seq}%
}
% \clearlist{listname} clear if exists
\cs_new:Npn \clearlist #1
{
\seq_clear_new:c {l_savecontent_content_#1_seq}%
}
% \addcontent{listname}{{}} ...need double {{...}}
\NewDocumentCommand{\addcontent}{m+m}
{
\savecontent_add_content:nn { #1 } { #2 }
}
% \usecontent[number]{listname}
\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 }
}
% define keys (local)
\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,%
%temp-ext .tl_set:N = \l_scontent_temp_ext_tl,%
%temp-nro .tl_set:N = \l_scontent_temp_nro_tl,%
name-tmp .tl_set:N = \l_scontent_tmp_name_tl,%
body-env .bool_set:N = \l_scontent_env_body_tl,%
body-cmd .bool_set:N = \l_scontent_cmd_body_tl,%
verb .meta:n = { body-env = false, body-cmd = false },%
show-all .meta:n = { show-env = true , show-cmd = true },%
}
% set local default
\keys_set:nn { scontent }
{
save-cmd = content, %
show-cmd = false,%
save-env = content, %
show-env = false,%
name-tmp = \jobname,%
body-env = true,%
body-cmd = true,%
}
% \Setscontent{ key = val }
\NewDocumentCommand{\Setscontent}{ +m}
{
\keys_set:nn { scontent } {#1}
}
% \envtolist pass \BODY to list name
\newrobustcmd{\envtolist}[1]{\addcontent{ \l_scontent_env_save_tl }{{#1}}}
% Define SAVEcontent to activate \BODY from environ
\NewEnviron{SAVEcontent}[1]{}
% counter for external tmp files
\newcounter{outNr}
\DeclareExpandableDocumentCommand{\tmpNr}{}{%
\arabic{outNr}
}
% \begin{scontent}[...] no space need !
\NewDocumentEnvironment{scontent}{ !o }
{%
\group_begin:
\IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
\IfBooleanT { \l_scontent_env_body_tl } { \SAVEcontent{#1} } % no \verb content
\IfBooleanF { \l_scontent_env_body_tl } {
\stepcounter{outNr}
\VerbatimEnvironment
\VerbatimOut{\l_scontent_tmp_name_tl-\theoutNr.tsc}} % \verb content
} % close first part
{
\IfBooleanF { \l_scontent_env_body_tl } {
\endVerbatimOut%
\envtolist{\input{\l_scontent_tmp_name_tl-\tmpNr.tsc}} % line whit counter ...
}
\IfBooleanT { \l_scontent_env_body_tl } { \endSAVEcontent\expandafter\envtolist\expandafter{\BODY} }%
\IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
\group_end:
} % close second part
% \Scontent[...]{...}
\NewDocumentCommand{\Scontent}{!o +m}
{
\group_begin:
\IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
\IfBooleanT { \l_scontent_cmd_body_tl } { \addcontent{ \l_scontent_cmd_save_tl }{{#2}} } % pass direct to list
\IfBooleanT { \l_scontent_cmd_show_tl } { \usecontent[-1]{ \l_scontent_cmd_save_tl} } %
\group_end:
}%
% put starred "*" in clasical... use * and [...] cause a problem whit \VerbatimOut :(
% use key = verb for solve this
%\cs_new:cpn {scontent*} {\scontent*}
%\cs_new_eq:cN {endscontent*} \endscontent
\ExplSyntaxOff
\begin{document}
\Setscontent{
save-env=test-env,% list for save env
save-cmd=test-cmd,% list for save cmd
}
\section{Test scontent env}
Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
\begin{scontent}
Text is hiden....no verb inside the block, and no use [...]...use environ
\end{scontent}
Now show save using \verb+\usecontent[1]{test-env}+\par
\usecontent[1]{test-env}\par
OK...continue\par
\begin{scontent}[verb]
Second Text using \verb+\verb+ in some lines...
\end{scontent}
Now show save using \verb+\usecontent[2]{test-env}+\par
\usecontent[2]{test-env}\par
OK...continue\par
\begin{scontent}[verb]
Third Text using \verb+\verb+ in some lines
\end{scontent}
Now show using \verb+\usecontent[3]{test-env}+\par
\usecontent[3]{test-env}\par
OK...continue\par
SOME LINE OF TEXT
Now reuse \verb+\usecontent[2]{test-env}+\par
\usecontent[2]{test-env}\par
NOT OK...show \verb+\usecontent[3]{test-env}+ :(
\section{Test Scontent comand}
\Scontent[show-cmd=true]{\unexpanded{using a command version, no verb in some lines}}
No \verb+\verb+ suported no escape for this...environ not suport this :(
\end{document}
我尝试使用\expandafter
,\noexpand
但无法使其工作:( 我怎样才能仅记录计数器的值,然后在使用命令时不更改它\usecontent
?
Saludos PS:如果有人有更好的想法来实现这一目标,我们很感激......
答案1
我自己已经解决了这个问题,我不知道代码是否完全正确,但是,它可以满足我的要求,我把它留在这里:
% Example OK
\documentclass{article}
\usepackage{environ,etoolbox,xparse,fvextra,xcolor}%
% Definitions
\ExplSyntaxOn
% \elementin{listname} number of elements in listname
\cs_new:Npn \elementin #1
{%
\seq_count:c {l_savecontent_content_#1_seq}%
}
% \clearlist{listname} clear if exists
\cs_new:Npn \clearlist #1
{
\seq_clear_new:c {l_savecontent_content_#1_seq}%
}
% \addcontent{listname}{{}} ...need double {{...}}
\NewDocumentCommand{\addcontent}{m+m}
{
\savecontent_add_content:nn { #1 } { #2 }
}
% \usecontent[number]{listname}
\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 }
}
% define keys (local)
\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,%
name-tmp .tl_set:N = \l_scontent_tmp_name_tl,%
body-env .bool_set:N = \l_scontent_env_body_tl,%
body-cmd .bool_set:N = \l_scontent_cmd_body_tl,%
verb .meta:n = { body-env = false, body-cmd = false },%
show-all .meta:n = { show-env = true , show-cmd = true },%
}
% set local default
\keys_set:nn { scontent }
{
save-cmd = content, %
show-cmd = false,%
save-env = content, %
show-env = false,%
name-tmp = \jobname,%
body-env = true,%
body-cmd = true,%
}
% \Setscontent{ key = val }
\NewDocumentCommand{\Setscontent}{ +m}
{
\keys_set:nn { scontent } {#1}
}
% \envtolist pass \BODY to list name
\newrobustcmd{\envtolist}[1]{\addcontent{ \l_scontent_env_save_tl }{{#1}}}
% counter for external tmp files
\newcounter{outNr}
% \filetolist for external tmp files
\tl_new:N \filetolist
% Define SAVEcontent to activate \BODY from environ
\NewEnviron{SAVEcontent}[1]{}
% \begin{scontent}[...] no space need !
\NewDocumentEnvironment{scontent}{ !o }
{%
\group_begin:
\IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
\IfBooleanT { \l_scontent_env_body_tl } { \SAVEcontent{#1} } % no verb content
\IfBooleanF { \l_scontent_env_body_tl } % verb content
{
\stepcounter{outNr}
\VerbatimOut{\l_scontent_tmp_name_tl-\theoutNr.tsc}
} % write out
} % close first part
{
\IfBooleanF { \l_scontent_env_body_tl }
{
\endVerbatimOut%
\tl_put_right:Nx \filetolist { \envtolist{\exp_not:N \input {\exp_after:wN \l_scontent_tmp_name_tl-\theoutNr.tsc} } }% \expandafter counter
\filetolist
%\show\filetolist
}
\IfBooleanT { \l_scontent_env_body_tl } { \endSAVEcontent\expandafter\envtolist\expandafter{\BODY} }%
\IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
\group_end:
} % close second part
% \Scontent[...]{...}
\NewDocumentCommand{\Scontent}{!o +m}
{
\group_begin:
\IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
\IfBooleanT { \l_scontent_cmd_body_tl } { \addcontent{ \l_scontent_cmd_save_tl }{{#2}} } % pass direct to list
\IfBooleanT { \l_scontent_cmd_show_tl } { \usecontent[-1]{ \l_scontent_cmd_save_tl} } %
\group_end:
}%
\ExplSyntaxOff
\begin{document}
% set name of list
\Setscontent{
save-env=test-env,% list for save env
save-cmd=test-cmd,% list for save cmd
}
\section{Test scontent env OK}
The following blocks of text will be stored in memory or in external files and
then referenced using lists, not shown directly.\par
\begin{scontent}
\textcolor{red}{First Text}....no verb inside the block, and no use [...]...use environ
\end{scontent}
% \jobname-1.tsc
\begin{scontent}[verb]
\textcolor{green}{Second Text}...save in \verb+\jobname-1.tsc+
\end{scontent}
% \jobname-2.tsc
\begin{scontent}[verb]
\textcolor{blue}{Third Text}...save in \verb+\jobname-2.tsc+
\end{scontent}
% \jobname-3.tsc
\begin{scontent}[verb]
\textcolor{gray}{Fourth Text}...save in \verb+\jobname-3.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[4]{test-env}\par\vspace{1cm}
\usecontent[3]{test-env}\par\vspace{1cm}
\usecontent[2]{test-env}\par\vspace{1cm}
\usecontent[1]{test-env}\par\vspace{1cm}
\section{Test scontent env other OK}
% \jobname-4.tsc
\begin{scontent}[save-env=other, verb]
\textcolor{magenta}{Other Text}...save in list \{other\} and write in \verb+\jobname-4.tsc+
\end{scontent}
Now show whit \verb+\usecontent{other}+:\par
\usecontent{other}
\section{Test Scontent comand OK}
\Scontent{using a command version, no verb\par in\par some\par lines}
No \verb+\verb+ suported no escape for this...environ not suport this :(. [no problem]
\usecontent{test-cmd}
\end{document}
显然这条线
\tl_put_right:Nx \filetolist { \envtolist{\exp_not:N \input {\exp_after:wN \l_scontent_tmp_name_tl-\theoutNr.tsc} } }% \expandafter counter
\filetolist
它不是正确的,它可以工作,但是在使用时:
pdflatex --recorder -newtest.tex & cat -n newtest.fls | grep "INPUT newtest"
输出为:
5 INPUT newtest.tex
56 INPUT newtest.aux
57 INPUT newtest.aux
67 INPUT newtest-3.tsc
68 INPUT newtest-3.tsc
69 INPUT newtest-2.tsc
70 INPUT newtest-2.tsc
71 INPUT newtest-1.tsc
72 INPUT newtest-1.tsc
74 INPUT newtest-4.tsc
75 INPUT newtest-4.tsc
80 INPUT newtest.aux
也就是说,\input
文件.tsc
两次,因为在示例中只调用了它们一次...我想这是另一个问题......