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