如何在处理时操作 SplitList 的项目?

如何在处理时操作 SplitList 的项目?

我使用 xparse 和 expl3 定义了一个新宏来生成一组两个列表。这个想法是让一个宏具有与旧宏相同的输出,这对用户非常不友好,因为我必须为不同数量的条目编写一个宏。在 siunitx.dtx 的帮助下,我能够编写一个宏,它生成的输出与旧宏的输出非常相似,但尚不相等。如您所见,旧宏使用数学模式,这使得条目之间的距离略小。

可能是因为我没有完全理解 SplitList 的每一个细节和不同的控制序列,我无法找到一种方法将第一个列表的每个项目定义为 \text{A}、\textbf{B} 等等,以便输出可以处于数学模式。

有没有办法以当前代码为起点来实现这一点?

编辑:

第一个列表应该是强制性的,并且至少包含一个条目 - 如果是这种情况,则只应打印第一个列表(第一个列表中的条目“A”应打印“A”)

如果第一个列表中至少有两个条目,则第二个列表中必须有两个条目(第一个列表中的条目“A; B”要求第二个列表中有条目“1; 2”。这应该打印“A:B = 1:2”)。

因为数学模式中的字母默认是斜体,所以第一个列表中的条目应该包装在 \text{} 宏中。

(終結編輯)

\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{nccmath}
\usepackage{listingsutf8}
\usepackage{siunitx}        % to be used
\usepackage{xspace}

\newcommand{\oldmacro}[6]{$\text{#1}:\text{#3}:\text{#5} = #2:#4:#6$\xspace}    % for comparison

\ExplSyntaxOn

%%% defining token list variables -----------------------------------

\tl_new:N \l_firstlist_tl
\tl_new:N \l_firstlist_current_tl
\tl_new:N \l_secondlist_tl
\tl_new:N \l_secondlist_current_tl

\tl_new:N \l_firstlist_separator_tl
\tl_new:N \l_secondlist_separator_tl
\tl_new:N \l_first_second_separator_tl

%%%%% setting the separators

\tl_set:Nn \l_firstlist_separator_tl {~:~}
\tl_set:Nn \l_secondlist_separator_tl {~:~}
\tl_set:Nn \l_first_second_separator_tl {~=~}

%%% defining boolean variables -----------------------------------

\bool_new:N \l_print_first_bool
\bool_new:N \l_print_first_second_bool
\bool_new:N \l_print_first_second_list_bool

%%% defining macros -----------------------------------

\NewDocumentCommand{\newmacro}{ >{ \SplitList { ; } } m     >{ \SplitList { ; } } g }
{

    \detailed_checks_func:nn {#1}{#2}
    \newmacro_process_func:nn {#1}{#2}
    \xspace
}

\cs_new_protected:Npn \detailed_checks_func:nn #1#2
{
    \bool_set_false:N \l_print_first_bool
    \bool_set_false:N \l_print_first_second_bool

    \tl_if_single:nTF {#1}
    {\tl_if_eq:nnTF {#1} {{}}
        {\textbf{Error~Message~1}}
        {\IfNoValueTF {#2}
            {\bool_set_true:N \l_print_first_bool}
            {\tl_if_single:nTF {#2}
                {\textbf{Error~Message~2}}
                {\textbf{Error~Message~3}}
            }
        }
    }
    {\detailed_nosingle_checks_func:nn {#1}{#2}}
}

\cs_new_protected:Npn \detailed_nosingle_checks_func:nn #1#2
{
    \IfNoValueTF {#2}
    {\textbf{Error~Message~4}}
    {\int_compare:nNnTF {\tl_count:n {#1}} = {\tl_count:n {#2}}
        {\bool_set_true:N \l_print_first_second_bool}
        {\int_compare:nNnTF {\tl_count:n {#1}} < {\tl_count:n {#2}}
            {\textbf{Error~Message~3}}
            {\int_compare:nNnTF {\tl_count:n {#1}} > {\tl_count:n {#2}}
                {\textbf{Error~Message~5}}
                {\textbf{Error~Message~6}}
            }
        }
    }
}

\cs_new_protected:Npn \newmacro_process_func:nn #1#2
{

    \bool_if:nT {\l_print_first_bool}
    {\firstlist_output_func:n {#1}}

        \bool_set_true:N {\l_print_first_second_list_bool}  % needed for testing purposes
    \bool_if:nT {\l_print_first_second_bool}
    {
        \bool_if:nT {\l_print_first_second_list_bool}
        {
            \tl_clear:N \l_firstlist_current_tl
            \tl_clear:N \l_firstlist_tl
            \tl_map_function:nN {#1} \firstlist_process_aux_func:n
            \l_firstlist_tl
            \l_firstlist_separator_tl
            \l_firstlist_current_tl
            \l_first_second_separator_tl
            \tl_clear:N \l_secondlist_current_tl
            \tl_clear:N \l_secondlist_tl
            \tl_map_function:nN {#2} \secondlist_process_aux_func:n
            \l_secondlist_tl
            \l_secondlist_separator_tl
            \l_secondlist_current_tl
        }
    }
}

%%% function for processing the firstlist -----
\cs_new_protected:Npn \firstlist_process_aux_func:n #1
{
    \tl_if_empty:NTF \l_firstlist_tl
    {\tl_set_eq:NN \l_firstlist_tl \l_firstlist_current_tl}             
    {
        \tl_put_right:NV \l_firstlist_tl \l_firstlist_separator_tl
        \tl_put_right:NV \l_firstlist_tl \l_firstlist_current_tl
    }
    \tl_set:Nn \l_firstlist_current_tl {\firstlist_output_func:n {#1}}
}

%%% function for printing the firstlist -----
\cs_new_protected:Npn \firstlist_output_func:n #1
{
    {#1}
}

%%% function for processing the secondlist -----
\cs_new_protected:Npn \secondlist_process_aux_func:n #1
{
    \tl_if_empty:NTF \l_secondlist_tl
    {\tl_set_eq:NN \l_secondlist_tl \l_secondlist_current_tl}               
    {
        \tl_put_right:NV \l_secondlist_tl \l_secondlist_separator_tl
        \tl_put_right:NV \l_secondlist_tl \l_secondlist_current_tl
    }
    \tl_set:Nn \l_secondlist_current_tl {\secondlist_output_func:n {#1}}
    }

%%% function for printing the secondlist -----
\cs_new_protected:Npn \secondlist_output_func:n #1
{
    {#1}
}

\ExplSyntaxOff

\begin{document}

    \section{Working Examples:}

    \lstinline|\newmacro{A}|: \newmacro{A}\\    
    \lstinline|\newmacro{A;B;C;D}{1;2;3;4}|: \newmacro{A;B;C;D}{1;2;3;4}

    \subsection{For Comparison:}

    $A:B:C=1:2:3$\\
    $\text{A}:\text{B}:\text{C}=1:2:3$ () \\
    \oldmacro{A}{1}{B}{2}{C}{3} (\lstinline|\oldmacro{A}{1}{B}{2}{C}{3}|)\\
    \newmacro{A;B;C}{1;2;3} (\lstinline|\newmacro{A;B;C}{1;2;3}|)\\
    A : B : C = 1 : 2 : 3\\

\end{document}

答案1

如果要使用数学模式,请在数学模式下调用宏。

这是一个实现:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\newmacro}{mm}
 {
  \echo_newmacro:nn { #1 } { #2 }
 }

\seq_new:N \l_echo_newmacro_first_seq
\seq_new:N \l_echo_newmacro_second_seq

\cs_new_protected:Nn \echo_newmacro:nn
 {
  \seq_set_split:Nnn \l_echo_newmacro_first_seq { ; } { #1 }
  \seq_set_split:Nnn \l_echo_newmacro_second_seq { ; } { #2 }
  \seq_use:Nn \l_echo_newmacro_first_seq { : }
  =
  \seq_use:Nn \l_echo_newmacro_second_seq { : }
 }
\ExplSyntaxOff

\begin{document}

$\newmacro{A;B;C}{1;2;3}$

$\newmacro{A;B;C;D}{1;2;3;4}$

\end{document}

在此处输入图片描述

完整规范后的新版本

请注意,由于第二部分是可选的,因此应在方括号中指定。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\newmacro}{mo}
 {
  \IfNoValueTF{ #2 }
   {
    \mathrm{#1}
   }
   {
    \echo_newmacro:nn { #1 } { #2 }
   }
 }

\seq_new:N \l_echo_newmacro_first_seq
\seq_new:N \l_echo_newmacro_second_seq

\cs_new_protected:Nn \echo_newmacro:nn
 {
  \seq_set_split:Nnn \l_echo_newmacro_first_seq { ; } { #1 }
  \seq_set_split:Nnn \l_echo_newmacro_second_seq { ; } { #2 }
  \int_compare:nTF
   {
    \seq_count:N \l_echo_newmacro_first_seq == \seq_count:N \l_echo_newmacro_second_seq
   }
   {% OK, the number of items is the same
    \mathrm{ \seq_use:Nn \l_echo_newmacro_first_seq { : } }
     =
    \seq_use:Nn \l_echo_newmacro_second_seq { : }
   }
   {% Error
    \msg_error:nnnn { echo/ratio } { wrong-number } { #1 } { #2 }
   }
 }
\msg_new:nnnn { echo/ratio } { wrong-number}
 {
  Wrong~number~of~items
 }
 {
  You~have~specified~lists~of~different~lengths~"#1"~and~"#2"
 }
\ExplSyntaxOff

\begin{document}

$\newmacro{A}$

$\newmacro{A;B;C}[1;2;3]$

$\newmacro{A;B;C;D}[1;2;3;4]$

$\newmacro{A}[1;2]$

\end{document}

在此处输入图片描述

最后一次调用触发错误:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! echo/ratio error: "wrong-number"
! 
! Wrong number of items
! 
! See the echo/ratio documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

l.54 $\newmacro{A}[1;2]
                       $
? h
|'''''''''''''''''''''''''''''''''''''''''''''''
| You have specified lists of different lengths "A" and "1;2"
|...............................................

相关内容