在宏内连续处理宏的序列

在宏内连续处理宏的序列

我有一个宏,它使用内部宏来处理参数对。基本部分可以分解为

\mymacro{\inside{A}{1};\inside{B}{2},\inside{C}{3}}

最初,我处理了所有对,然后打印出来,用逗号分隔,使用序列来获得输出,例如“1A,2B,3C”,“1A,2B”或“1A”,分别代表三个,两个和一个参数。

现在要求已经改变,我需要输出为:“1,A 2,B 3.C”,“1,A 2.B”或“1.A”。

我想,这可以通过序列来完成,并提出了这个解决方案:

\documentclass{article}
\usepackage{xparse,expl3} % expl3 loaded explicitly - not necessary because it is already loaded by xparse
\ExplSyntaxOn

\tl_new:N \l__map_current_tl
\tl_new:N \l__map_tl
\tl_new:N \l__inside_tl

\seq_new:N \l__my_seq
\seq_new:N \l__second_seq

\NewDocumentCommand \mymacro {>{\SplitList{;}} m}
{
    \mymacro_process_func:n {#1}
    \mymacro_output_func:n
    \\
}

\NewDocumentCommand \inside {m m}
{
    \inside_process_func:nn {#1} {#2}
}

\cs_new_protected:Npn \inside_process_func:nn #1 #2
{
    \tl_if_empty:NTF \l__inside_tl
    { \tl_put_right:Nn \l__inside_tl {#2 !! #1} }
    { \tl_put_right:Nn \l__inside_tl {~ #2 !! #1} }
}

\cs_new_protected:Npn \mymacro_process_func:n #1
{
    % make sure token lists and sequences are empty
    \tl_clear:N \l__map_current_tl
    \tl_clear:N \l__map_tl
    \tl_clear:N \l__inside_tl

    \seq_clear:N \l__my_seq
    \seq_clear:N \l__second_seq

    \tl_map_function:nN {#1} \mymacro_map_func:n
    \tl_show:N {\l__map_tl}
    \seq_set_split:NnV \l__my_seq {;} \l__map_tl
%   \seq_show:N \l__my_seq
    \seq_use:Nnnn \l__my_seq {} {} {}
}

\cs_new_protected:Npn \mymacro_map_func:n #1
{
    \tl_set:Nn \l__map_current_tl {#1}
    \tl_if_empty:NTF \l__map_tl
    { \tl_set_eq:NN \l__map_tl \l__map_current_tl }
    {
        \tl_put_right:Nn \l__map_tl {;}
        \tl_put_right:NV \l__map_tl \l__map_current_tl
    }
    \tl_set:Nn \l__map_current_tl {#1}
}

\cs_new_protected:Npn \mymacro_output_func:n 
{
    \seq_set_split:NnV \l__second_seq {!!} \l__inside_tl
%   \seq_show:N \l__second_seq
    \seq_use:Nnnn \l__second_seq {.} {,} {.}
}

\ExplSyntaxOff

\begin{document}

Achieved:\\
\mymacro{\inside{A}{1}}
\mymacro{\inside{A}{1};\inside{B}{2}}
\mymacro{\inside{A}{1};\inside{B}{2};\inside{C}{3}}

Desired:\\
1.A \\ 1,A 2.B \\ 1,A 2,B 3.C

\end{document}

如您所见,代码完成了应有的工作:

序列输出

但是,我担心它效率不高,而且对我来说看起来很可疑。例如,我在以前的版本中使用了带空格的\l__my_seqin :\mymacro_process_func:n

\seq_set_split:NnV \l__my_seq {;} \l__map_tl
\seq_use:Nnnn \l__my_seq {~} {~} {~}

但空格没有出现在输出中。(实际上,用 all 替换会~?输出前分别打印无问号、一个问号或两个问号。)

  • 有没有更好(更短)的方法来而无需改变\mymacro和的使用\inside(我无法更改文档中的所有宏)
  • 总的来说,有没有更好的方法来解决此问题?

顺便说一句:我不确定我的解决方案(命名等)是否符合所有规则和惯例,因此对此的任何评论也值得赞赏。

答案1

如果我理解了这个要求,似乎你不需要循环输入,你可以简单地执行列表,并在进行时排版每个项目。

在此处输入图片描述

\documentclass{article}

\def\mymacro#1{#1\relax}
\def\inside#1#2#3{\ifx\relax#3#2.#1\else#2,#1 \fi}

\begin{document}


Achieved:\\
\mymacro{\inside{A}{1}}\\
\mymacro{\inside{A}{1};\inside{B}{2}}\\
\mymacro{\inside{A}{1};\inside{B}{2};\inside{C}{3}}

Desired:\\
1.A \\ 1,A 2.B \\ 1,A 2,B 3.C


\end{document}

相关内容