计算标记列表中给定字符的数量并应用相应的操作

计算标记列表中给定字符的数量并应用相应的操作

我想定义一个命令,计算输入中子字符串的数量,并根据结果应用相应的操作。

例如,在下面的代码中,命令应该根据.输入的数量应用相应的规则。

\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

关于金文的回答

  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 }
      {
        ...
      }
    
  2. 以下是另一种使用\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\.正则表达式。

  3. 您的函数最好用\cs_new_protected:Nn而不是 来定义\cs_new:Nn,因为它无法在仅扩展的上下文中完成其工作(例如在 内部\edef\write许多其他上下文;例如,参见“附件”这里一些解释)。其中一个原因是,无论是\seq_set_split:Nnn(在你的版本中)还是\regex_count:nnN(在我的版本中)可扩展—寻找左边距的星星界面3.pdf

  4. 两种计数技术是不等同于,因为\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

结果与接受的答案相同。

相关内容