如何扩展 \macro(或副本)以保存在 xparse (expl3) 中环境末尾的列表中?

如何扩展 \macro(或副本)以保存在 xparse (expl3) 中环境末尾的列表中?

我正在尝试封装几个环境,以便使用将它们传递给列表xparse/expl3。我定义了一个命令和两个环境,但其中一个出现了问题。

我使用环境来保存笔记类型问题/答案将答案存储在列表中以显示在文件末尾或其他位置,问题是有时需要逐字使用。

环境scontent使用+b的参数xparse,并且只能使用Verb[...]{...}(from fvextra)(例如,不能使用 verbatim 环境)。

scontent*环境基于filecontentsdef并可verb|...|在一行或\begin{verbatim}环境中使用,这会生成一个外部文件,但可以将内容保存在\macro.

执行时\begin{scontent*}传递以下内容:

  1. 保存当前内容\macro
  2. \macro复制当前内容\l_my_macro_copy_tl
  3. 使用以下方式将内容传递\l_my_macro_copy_tl到列表中 \expanddafter\envtolist\expanddafter{ content save in \l_my_macro_copy_tl}
  4. 如果这是关键的[show-env = true]跑动\usecontent[-1]{\l_scontent_env_save_tl}

问题在于执行

\expanddafter\envtolist\expanddafter{\l_my_macro_copy_tl}

在环境结束时scontent*,我尝试了以下(丑陋且不正确的)行:

% \begin{scontent*}[...] verbatim env save in \macro
% Copy a current content of \macro in \l_my_macro_copy_tl and pass to list
\tl_new:N \l_my_macro_copy_tl
\NewDocumentEnvironment{scontent*}{ !O{} }
 { 
  \group_begin:
  \filecontentsdef{\jobname.tsc}{\macro} % save in \macro
 }{
  \endfilecontentsdef %
  \group_end:
  \IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
  \tl_set:Nx \l_my_macro_copy_tl \macro 
  \exp_after:wN \envtolist \exp_after:wN { \exp_not:N \tex_newlinechar:D = 13 \exp_not:N \scantokens \exp_after:wN { \l_my_macro_copy_tl } }%
  \IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  }

通过这个,我消除了编译时的错误,但是内容没有保存在列表中......我怎样才能解决这个问题?

我的想法是不要直接占用\showme{...},只\usecontent[index]{list name}在文档中使用。

我知道如果在环境之外执行该命令,它会起作用,但我的想法是在运行时自动执行该\showme{...}命令。\usecontent[index]{list name}scontent*

这是我的示例文件(MWE),应该删除注释才能查看发生的错误。

\documentclass{article}
\usepackage{filecontentsdef,etoolbox,xparse,fvextra,xcolor}
\usepackage[margin=0.6in,noheadfoot,papersize={8.5in,13in}]{geometry}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\ExplSyntaxOn
% show content save in \macro
\tl_new:N \l_temp_argument_tl
\NewDocumentCommand\showme{ +m }{%
 \tl_set:Nx \l_temp_argument_tl { #1 }
 \tex_newlinechar:D = 13
 \exp_not:N { \scantokens \exp_after:wN { \l_temp_argument_tl } }
}

% \elementin{listname} and \clearlist{listname}
\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} }

% \addcontent{listname}{{#1}} ...need double {{...}}
\NewDocumentCommand{\addcontent}{ m +m } { \savecontent_add_content:nn { #1 } { #2 } }

% \usecontent[index]{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 } }

\keys_define:nn { scontent }
 {
    save-cmd .tl_set:N   = \l_scontent_cmd_save_tl, save-cmd .initial:n  = content,%
    save-env .tl_set:N   = \l_scontent_env_save_tl, save-env .initial:n  = content, %
    show-cmd .bool_set:N = \l_scontent_cmd_show_tl, show-cmd .initial:n  = false, show-cmd .value_required:n = true,%
    show-env .bool_set:N = \l_scontent_env_show_tl, show-env .initial:n  = false, show-env .value_required:n = true,%
    show-all .meta:n     = { show-env = true , show-cmd = true },%
 }

\NewDocumentCommand{\Setscontent}{ +m } { \keys_set:nn { scontent } {#1} }

% pass to list
\newrobustcmd{\envtolist}[1]{\addcontent{ \l_scontent_env_save_tl }{{#1}}}

% \Scontent[...]{...} NO verbatim env support, but \Verb[...]{...} yes
\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} }
  \group_end:
 }

% \begin{scontent}[...] NO verbatim env suport, but \Verb[...]{...} yes
\NewDocumentEnvironment{scontent}{ !o +b }
 {
  \group_begin:
  \IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
 }{
  \expandafter\envtolist\expandafter{#2}
  \IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  \group_end:
 }

% \begin{scontent*}[...] verbatim env save in \macro
\tl_new:N \l_my_macro_copy_tl % \tl_var to copy \macro at definition time
\NewDocumentEnvironment{scontent*}{ !O{} }
 {
  \group_begin:
  \IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
  \filecontentsdef{\jobname.tsc}{\macro}
 }{
  \endfilecontentsdef %
  \group_end:
  % Copy \macro every time in \tl_var (at definition time) and pass to list
  %\cs_set_eq:NN \l_my_macro_copy_tl \macro
  %\expandafter\envtolist\expandafter\showme{\l_my_macro_copy_tl}
  %\IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }    
 }
\ExplSyntaxOff
% set name of lists
\Setscontent{ save-env=test-env, save-cmd=test-cmd }
\begin{document}
\section{Using \texttt{scontent} environment whit new \texttt{+b} argument from \texttt{xparse}}
\subsection{Whit \texttt{[show-env=false]}}
Text save in \verb|\begin{scontent}[show-env=false]| (hidden)

\begin{scontent}[show-env=false]
Some first text whit verbatim inline saved in \Verb{\usecontent[1]{test-env}} \par
We have coded this in \LaTeX: both $E=mc^2$.
\end{scontent}

OK
\subsection{Whit \texttt{[show-env=true]}}
Text save in \verb|\begin{scontent}[show-env=true]| (Not hidden)

\begin{scontent}[show-env=true]
Some second text whit verbatim inline saved in \Verb{\usecontent[2]{test-env}}...more text \par
We have coded this in \LaTeX: both $E=mc^2$.
\end{scontent}

OK
\subsection{Using \Verb{\usecontent[1]{test-env}}}
Now see saved text in list:\par
\usecontent[2]{test-env}\par
\usecontent[1]{test-env}

\section{Using \Verb*{\Scontent[...]{...}}}
Text save whit \verb|\Scontent{....}| (hidden)\par
\Scontent{
using a \Verb*{\Scontent[...]{...}} \textcolor{red}{whit verbatim}  \Verb*{\Verb[...]{...}}\par
(by \Verb*{fvextra}) \textcolor{magenta}{inline}
}\par

And see saved text in list using \verb|\usecontent[1]{test-cmd}| \par
\usecontent[1]{test-cmd}\par
OK
\section{Using \texttt{scontent*} environment wraped \texttt{filecontentsdef} using \texttt{xparse}}

\subsection{Whit \texttt{[show-env=false]}}
Some Text save using \verb|\begin{scontent*}[show-env=false]| save in \verb|\macro| (hidden)

\begin{scontent*}[show-env=false]
Some text in whit verbatim environment ¿saved in list ...\verb+\usecontent[3]{test-env}+?(not get for now).\par
\begin{Verbatim}
           This is from the verbatim environment:  &%{}_"`´~
      xxxxx
\end{Verbatim}
\end{scontent*}\par
OK...it's posible to see \verb|\macro| whit \verb|\showme{\macro}|:\par
\showme{\macro}\par
or pass to list using \verb|\Scontent{\showme{\macro}}| and see in list whit \verb+\usecontent[2]{test-cmd}+:\par
\Scontent{\showme{\macro}}
\usecontent[2]{test-cmd}
\subsection{The idea whit \texttt{[show-env=true]}}
\Setscontent{ save-cmd=test-other }
XXXXXXXXX\par
\begin{scontent*}[show-env=false]
Some text in whit verbatim A
\begin{Verbatim}
   verbatim environment A:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}
\Scontent[show-cmd=true]{\showme{\macro}}\par
XXXXXXXXX\par
\begin{scontent*}[show-env=false]
Some text in whit verbatim B
\begin{Verbatim}
   verbatim environment B:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}
\Scontent[show-cmd=true]{\showme{\macro}}
XXXXXXXXX\par
And see in reverse order:\par
\usecontent[2]{test-other}\par
\usecontent[1]{test-other}\par
NOT OK,... 
\subsection{The problem whit \texttt{[show-env=true]}}
\begin{scontent*}[show-env=true]
Some text in whit verbatim C
\begin{Verbatim}
   verbatim environment C:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}
\end{document}

问候

答案1

在仔细查看了文档并阅读了论坛上的大量资料后,我设法自己完成了...

% arara: lualatex
% arara: clean: { extensions: [ aux, log, tsc] }
\documentclass{article}
\usepackage{filecontentsdef,xparse,fvextra,xcolor}
\usepackage[margin=0.6in,noheadfoot,papersize={8.5in,13in}]{geometry}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\makeatletter
\ExplSyntaxOn
% \elementin{listname}
\cs_new:Npn \elementin #1
 {
  \seq_count:c { l_savecontent_content_#1_seq }
 }

% \clearlist{listname}
\cs_new:Npn \clearlist #1
 {
  \seq_clear_new:c { l_savecontent_content_#1_seq }
 }

% \@add@content{listname}{{#1}} ...need double {{...}}
\NewDocumentCommand{\@add@content}{ m +m }
 {
  \savecontent_add_content:nn { #1 } { #2 }
 }

% \usecontent[index]{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 }
 }

\keys_define:nn { scontent }
 {
  save-cmd .tl_set:N         = \l_scontent_cmd_save_tl,%
  save-cmd .initial:n        = content,%
  save-env .tl_set:N         = \l_scontent_env_save_tl,%
  save-env .initial:n        = content,%
  show-cmd .bool_set:N       = \l_scontent_cmd_show_tl,%
  show-cmd .initial:n        = false,%
  show-cmd .value_required:n = true,%
  show-env .bool_set:N       = \l_scontent_env_show_tl,%
  show-env .initial:n        = false,%
  show-env .value_required:n = true,%
  show-all .meta:n           = { show-env = true , show-cmd = true },%
 }

\NewDocumentCommand{\Setscontent}{ +m }
 {
  \keys_set:nn { scontent } {#1}
 }

% \Scontent[...]{...} NO verbatim env support, but \Verb[...]{...} yes
\NewDocumentCommand{\Scontent}{ O{} +m }
 {
  \group_begin:
  \IfNoValueF{ #1 } { \keys_set:nn { scontent } {#1} }
  \@add@content{ \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:
 }

% \begin{scontent}[...] NO verbatim env suport, but \Verb[...]{...} yes
\NewDocumentEnvironment{scontent}{ !o +b }
 {
  \group_begin:
  \IfNoValueF{ #1 } { \keys_set:nn { scontent } {#1} }
 }{
  \@add@content{ \l_scontent_env_save_tl }{ { #2 } } % pass direct to list
  \IfBooleanT{ \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  \group_end:
 }

% \begin{scontent*}[...] verbatim env suport in \macro
\tl_new:N \l_add_@temp@save@content_tl
\NewDocumentEnvironment{scontent*}{ !O{} }
 {
  \group_begin:
  % save a tmp file.tsc in \@temp@save@content
  \filecontentsdef{\jobname.tsc}{\@temp@save@content}
 }{
  \endfilecontentsdef%
  \group_end:
  \group_begin:
  \IfNoValueF{ #1 } { \keys_set:nn { scontent } {#1} }
  % copy \@temp@save@content in \l_tmpa_tl
  \tl_set:Nx \l_tmpa_tl \@temp@save@content
  % expand \l_tmpa_tl in \l_tmpb_tl
  \tl_put_right:Nx \l_tmpb_tl
    {
     \tex_newlinechar:D = 13 \tex_everyeof:D = {\noexpand}
     \exp_not:N \scantokens \exp_after:wN { \l_tmpa_tl }
    }
  % pass \l_tmpb_tl to list
  \tl_put_right:Nx \l_add_@temp@save@content_tl
    {
     \exp_not:N \@add@content { \exp_not:V \l_scontent_env_save_tl } { {\exp_not:V \l_tmpb_tl } }
    }
  \l_add_@temp@save@content_tl
  \IfBooleanT{ \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  \group_end:
  }
\ExplSyntaxOff
\makeatother
% set name of lists
\Setscontent{ save-env=test-env, save-cmd=test-cmd }
\begin{document}
\section{Using \Verb{scontent} environment (\Verb{+b} argument from \Verb{xparse})}
\subsection{Whit \texttt{[show-env=false]}}
Text save in \verb|\begin{scontent}[show-env=false]| (hidden)

\begin{scontent}[show-env=false]
first text whit verbatim inline saved in \Verb{\usecontent[1]{test-env}} \par
We have coded this in \LaTeX: both $E=mc^2$.
\end{scontent}

\subsection{Whit \Verb{[show-env=true]}}
Text save in \verb|\begin{scontent}[show-env=true]| (Not hidden)\par

\begin{scontent}[show-env=true]
second text whit verbatim inline saved in \Verb{\usecontent[2]{test-env}}\par
More code in \LaTeX: both $E=mc^2$.
\end{scontent}

\section{Using \Verb{scontent*} environment (wraped \Verb{filecontentsdef})}

\subsection{Whit \Verb{[show-env=false]}}
Some Text save using \verb|\begin{scontent*}[show-env=false]| save in \verb|\macro| (hidden)

\begin{scontent*}[show-env=false]
Text in whit verbatim  environment ... saved in list ...\verb+\usecontent[3]{test-env}+.\par
\begin{Verbatim}
      (A) verbatim environment:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}

\subsection{Whit \Verb{[show-env=true]}}
Some Text save using \verb|\begin{scontent*}[show-env=true]| save in \verb|\macro| (Not hidden)

\begin{scontent*}[show-env=true]
Text in whit verbatim  environment ... saved in list ...\verb+\usecontent[4]{test-env}+.\par
\begin{Verbatim}
      (B) verbatim environment:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}

\section{Using \Verb{\Scontent[...]{...}}}
\subsection{Whit \texttt{[show-cmd=false]}}
Text save whit \verb|\Scontent[show-cmd=false]{....}| (hidden)\par

\Scontent[show-cmd=false]{
using a \Verb*{\Scontent[show-cmd=false]{...}} \textcolor{red}{whit verbatim}  saved in \Verb*{\usecontent[1]{test-cmd}}\par
(by \Verb*{fvextra}) \textcolor{magenta}{inline}
}\par

\subsection{Whit \Verb{[show-cmd=true]}}
Text save whit \verb|\Scontent[show-cmd=true]{....}| (Not hidden)\par
\Scontent[show-cmd=true]{
using a \Verb*{\Scontent[show-cmd=true]{...}} \textcolor{green}{whit verbatim} saved in \Verb*{\usecontent[2]{test-cmd}}\par
(by \Verb*{fvextra}) \textcolor{blue}{inline}
}

\section{Using \Verb{\usecontent[index]{list name}}}

\subsection{\Verb{\usecontent[index]{test-env}}}
Now see the \elementin{test-env} environment saved in list (reverse order):\par
\usecontent[4]{test-env}\par
\usecontent[3]{test-env}\par
\usecontent[2]{test-env}\par
\usecontent[1]{test-env}

\subsection{\Verb{\usecontent[index]{test-cmd}}}
Now see the \elementin{test-cmd} command saved in list (reverse order):\par
\usecontent[2]{test-cmd}\par
\usecontent[1]{test-cmd}\par
\end{document}

现在它按预期工作 工作正常 我澄清一下,如果没有以下出色的答案,这是不可能的:

  1. expl3:\tl_put_right:Nx 窒息{
  2. 如何在 \edef 中执行 \scantokens 而不触发“失控定义”
  3. 在命令中存储字符串数组
  4. 收集环境内容并存储以供日后检索

非常感谢参与这个社区的所有人……

相关内容