我如何使用 expl3 为活动角色赋予定义?

我如何使用 expl3 为活动角色赋予定义?

texdoc interface3这一点在……中被大大掩盖了。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \Digits { m m }{
  \group_begin:
    \char_set_catcode_active:N ;
    \char_set_catcode_active:N .

    \def;{,\;}
    \def.{\dots}

    \langle #1 \rangle \sb #2
  \group_end:
}
\ExplSyntaxOff

\begin{document}
Desired syntax:
  $\Digits{1,2,3;4,5,6;.;,7}{8}$

Desired output:
  $\langle 1,2,3, \; 4,5,6, \; \dots, \; 7 \rangle_8$
\end{document}

我稍后会用逗号列表做一些奇特的事情(使用l3clist),但我想先让这个语法发挥作用。

我认为这应该基于TeX 常见问题解答文章,但我一直收到以下错误:

ERROR: Missing control sequence inserted.

--- TeX said ---
<inserted text> 
                \inaccessible 
l.18 $\Digits{1,2,3;4,5,6;.;,7}{8}
                                  $
--- HELP ---
This is probably caused by a \newcommand, \renewcommand, \newlength,
or \newsavebox command whose first argument is not a command name.

根据 cgnieder 的评论,也许以下方法可行:

\NewDocumentCommand \Digits { s m m } {
  \group_begin:
    \seq_set_split:Nnn
      \l_digit_seq
      { #2 }
      { \IfBooleanTF { #1 } { } { , } }

    \char_set_catcode_active:N ;
    \char_set_catcode_active:N .

    \def;{,\;}
    \def.{\dots}

    \real_digits:nn
}

\cs_new:Npn \real_digits:nn #1 #2 {
  \langle #1 \rangle \sb #2
  \group_end:
}
\ExplSyntaxOff

但不幸的是,事实并非如此。

答案1

这与通常的 TeX 编程没什么不同。在这种情况下,我们可以利用制作字符的可能性数学活跃以及 提供的高级活跃角色管理expl3

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\cs_new:Npn \sean_active_define:NN #1 #2
 {
  % define the active version of character #1 to do #2
  \char_set_active_eq:nN { `#1 } #2
  % make #1 math active
  \char_set_mathcode:nn { `#1 } { "8000 }
}

\NewDocumentCommand \Digits { m m }
 {
  % limit the scope of the math active characters
  \group_begin:
  \sean_active_define:NN ; \__sean_active_semicolon:
  \sean_active_define:NN . \__sean_active_period:
  \langle #1 \rangle\sb{#2}
  \group_end:
 }

\cs_new_protected:Npn \__sean_active_semicolon: { ,\; }
\cs_new_protected:Npn \__sean_active_period: { \dots }
\ExplSyntaxOff

\begin{document}
\makebox[3cm][l]{Desired syntax:}
  \verb$\Digits{1,2,3;4,5,6;.;7}{8}$

\makebox[3cm][l]{Obtained output:}
  $\Digits{1,2,3;4,5,6;.;7}{8}$

\makebox[3cm][l]{Desired output:}
  $\langle 1,2,3, \; 4,5,6, \; \dots, \; 7 \rangle_8$
\end{document}

在此处输入图片描述

笔记。l3 内核的最新版本(2015 年 9 月)改进了活动字符的管理。


旧版

它与通常的 TeX 编程没有什么不同;类别代码在存储定义时是固定的,并且在您的定义中;具有.类别代码 12。

该过程需要使用\tl_to_lowercase:n以获得所请求的活动字符,同时能够在替换文本中使用它们。

这是一个可能的实现,具有通用activation函数;的定义\Digits不应该有参数,以避免在激活角色后吸收参数。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\group_begin:
\char_set_catcode_active:N \^^@
\cs_new:Npn \sean_active_define:NN #1 #2
 {
  \group_begin: 
  \char_set_lccode:nn { `^^@ } { `#1 }
  \tl_to_lowercase:n
   {
    \group_end:
    \cs_set_eq:NN ^^@
   }
   #2 % the replacement text is better outside \tl_to_lowercase:n
   \char_set_catcode_active:N #1
}
\group_end:

\NewDocumentCommand \Digits { }
 {
  \group_begin:
  \sean_active_define:NN ; \__sean_active_semicolon:
  \sean_active_define:NN . \__sean_active_period:
  \sean_digits:nn
 }

\cs_new_protected:Npn \sean_digits:nn #1 #2
 {
  \langle #1 \rangle\sb{#2}
  \group_end:
 }

\cs_new_protected:Npn \__sean_active_semicolon: { ,\; }
\cs_new_protected:Npn \__sean_active_period: { \dots }
\ExplSyntaxOff

\begin{document}
\makebox[2.5cm][l]{Desired syntax:}
  $\Digits{1,2,3;4,5,6;.;7}{8}$

\makebox[2.5cm][l]{Desired output:}
  $\langle 1,2,3, \; 4,5,6, \; \dots, \; 7 \rangle_8$
\end{document}

在此处输入图片描述

您可以通过使字符“数学活跃”来避免激活字符,这样就不需要分两个阶段吸收参数。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\group_begin:
\char_set_catcode_active:N \^^@
\cs_new:Npn \sean_math_active_define:NN #1 #2
 {
  \group_begin: 
  \char_set_lccode:nn { `^^@ } { `#1 }
  \tl_to_lowercase:n
   {
    \group_end:
    \cs_set_eq:NN ^^@
   }
   #2 % the replacement text is better outside \tl_to_lowercase:n
   \char_set_mathcode:nn { `#1 } { "8000 }
}
\group_end:

\NewDocumentCommand \Digits { m m }
 {
  \group_begin:
  \sean_math_active_define:NN ; \__sean_active_semicolon:
  \sean_math_active_define:NN . \__sean_active_period:
  \langle #1 \rangle\sb{#2}
  \group_end:
 }

\cs_new_protected:Npn \__sean_active_semicolon: { ,\; }
\cs_new_protected:Npn \__sean_active_period: { \dots }

\ExplSyntaxOff

\begin{document}
\makebox[2.5cm][l]{Desired syntax:}
  $\Digits{1,2,3;4,5,6;.;7}{8}$

\makebox[2.5cm][l]{Desired output:}
  $\langle 1,2,3, \; 4,5,6, \; \dots, \; 7 \rangle_8$
\end{document}

注意:我稍微改变了实现,使其更强大且更易于管理;现在可以轻松地使用参数定义本地活动字符。

相关内容