如何使用 xparse 扩展辅助文件的计数器并将其保存在列表中?

如何使用 xparse 扩展辅助文件的计数器并将其保存在列表中?

我正在使用宏的修改来使用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两次,因为在示例中只调用了它们一次...我想这是另一个问题......

相关内容