我想定义一个命令,计算输入中子字符串的数量,并根据结果应用相应的操作。
例如,在下面的代码中,命令应该根据.
输入的数量应用相应的规则。
\documentclass{article}
\usepackage{xcolor}
\begin{document}
\ExplSyntaxOn
\cs_new:Nn \mymodule_apply_title_numbering_style_variant:n
{
\tl_set:Nx \l_tmpa_tl { #1 }
%% If #1 contains no '.'
\Huge\color{black}
%% If #1 contains one '.'
\large\color{black!80}
%% If #1 contains two '.'
\normalsize\color{black!60}
%% If #1 contains three '.'
\footnotesize\color{black!30}
\l_tmpa_tl
}
\mymodule_apply_title_numbering_style_variant:n { 1 }\par
\mymodule_apply_title_numbering_style_variant:n { 1.1 }\par
\mymodule_apply_title_numbering_style_variant:n { 1.1.1 }\par
\mymodule_apply_title_numbering_style_variant:n { 1.1.1.1 }
\end{document}
如何实现这一点?
答案1
关于金文的回答:
\int_case:nn
期望将⟨整数表达式⟩作为其第一个参数。由于\seq_count:N \l_tmpa_seq
递归扩展为⟨整数表示⟩,\seq_count:N \l_tmpa_seq - 1
因此是具有所需值的有效⟨整数表达式⟩;因此,\int_eval:n
引用答案中的括号和括号都不是必需的。换句话说,您可以使用:\seq_set_split:Nnn \l_tmpa_seq { . } {#1} \int_case:nn { \seq_count:N \l_tmpa_seq - 1 } { ... }
以下是另一种使用
\regex_count:nnN
计数句点和\int_case:nnF
(而不是\int_case:nn
)来实现“else”子句的方法:\documentclass{article} \usepackage{xcolor} \begin{document} \ExplSyntaxOn \cs_new_protected:Nn \mymodule_apply_title_numbering_style_variant:n { \group_begin: \regex_count:nnN { \. } {#1} \l_tmpa_int \int_case:nnF { \l_tmpa_int } { { 0 } { \Huge\color{black} } { 1 } { \large\color{black!80} } { 2 } { \normalsize\color{black!60} } } { \footnotesize\color{black!30} } #1 \group_end: } \mymodule_apply_title_numbering_style_variant:n { 1 }\par \mymodule_apply_title_numbering_style_variant:n { 1.1 }\par \mymodule_apply_title_numbering_style_variant:n { 1.1.1 }\par \mymodule_apply_title_numbering_style_variant:n { 1.1.1.1 }\par \mymodule_apply_title_numbering_style_variant:n { 1.1.1.1.1 }\par \mymodule_apply_title_numbering_style_variant:n { 1.1.1.1.1.1 } \ExplSyntaxOff \end{document}
注意:
l3regex
正则表达式\.
匹配任何类别代码的句点。例如,如果您只想匹配 catcode-12 句点(即“正常”句点),请使用\cO\.
正则表达式。您的函数最好用
\cs_new_protected:Nn
而不是 来定义\cs_new:Nn
,因为它无法在仅扩展的上下文中完成其工作(例如在 内部\edef
,\write
许多其他上下文;例如,参见“附件”这里一些解释)。其中一个原因是,无论是\seq_set_split:Nnn
(在你的版本中)还是\regex_count:nnN
(在我的版本中)可扩展—寻找左边距的星星界面3.pdf。两种计数技术是不等同于,因为
\seq_set_split:Nnn
会创建带括号平衡的项,而\regex_count:nnN
只会遍历指定的标记列表,而不会特别考虑括号。因此,以1{.}1
作为函数的输入,基于的技术\seq_set_split:Nnn
找不到句点,而基于的技术则只\regex_count:nnN
找到一个句点。
答案2
下面的代码是第一次尝试,请参阅@fougon 接受的答案以获得澄清和改进。
这是我刚刚发现的一个解决方案,感谢 Jasper Habicht 在该问题的评论中提供的链接。
\documentclass{article}
\usepackage{xcolor}
\begin{document}
\ExplSyntaxOn
\cs_new:Nn \mymodule_apply_title_numbering_style_variant:n
{
\group_begin:
\seq_set_split:Nnn \l_tmpa_seq { . } { #1 }
\int_case:nn { \int_eval:n {(\seq_count:N \l_tmpa_seq) - 1 } }
{
{ 0 } { \Huge\color{black} }
{ 1 } { \large\color{black!80} }
{ 2 } { \normalsize\color{black!60} }
{ 3 } { \footnotesize\color{black!30} }
}
#1
\group_end:
}
\mymodule_apply_title_numbering_style_variant:n { 1 }\par
\mymodule_apply_title_numbering_style_variant:n { 1.1 }\par
\mymodule_apply_title_numbering_style_variant:n { 1.1.1 }\par
\mymodule_apply_title_numbering_style_variant:n { 1.1.1.1 }
\end{document}
答案3
在 OpTeX 中,我们可以这样做:
\def\countdot#1{\tmpnum=0 \ea\foreach\detokenize{#1}\do{\ifx.##1\incr\tmpnum\fi}}
\def\titlestyle#1{%
\countdot{#1}% number of dots is saved in \tmpnum
\bgroup
\ifcase\tmpnum \typosize[17/]\or
\typosize[14/]\setgreycolor{.2}\or
\typosize[10/]\setgreycolor{.4}\else
\typosize[8/]\setgreycolor{.7}\fi
#1\par\egroup
}
% test:
\titlestyle {1}
\titlestyle {1.1}
\titlestyle {1.1.1}
\titlestyle {1.1.1.1}
\titlestyle {1.1.1.1.1}
\titlestyle {1.1.1.1.1.1}
\bye
结果与接受的答案相同。