如何定义在缩写(首字母缩写)中放置句点的命令?

如何定义在缩写(首字母缩写)中放置句点的命令?

有没有一种简单的方法来定义一个命令,该命令接受一个单词(首字母缩写)并在每个字符后插入一个句点?也就是说,我想定义一个\init{abc}输出“ABC”的命令(不假设输入参数中的字符数)。

预期用途是能够根据所需样式将 的输出切换\init{#1}\uppercase{#1}\textsc{#1},或像《纽约客》那样区分首字母缩略词,如 CPU(每个字母单独发音)和 NASA(发音为一个单词)。

答案1

您可以在每个标记处拆分输入,然后用句点分隔它们;\initformat您可以选择格式,参数应该是一个参数宏,例如\MakeUppercase\textsc

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\init}{m}
 {
  \tanh_init:n { #1 }
 }
\NewDocumentCommand{\initformat}{m}
 {
  \cs_set_eq:NN \tanh_init_format:n #1
 }

\seq_new:N \l_tanh_init_seq

\cs_new_protected:Nn \tanh_init:n
 {
  \seq_set_split:Nnn \l_tanh_init_seq { } { #1 }
  \tanh_init_format:n { \seq_use:Nn \l_tanh_init_seq { . } .\@ }
 }
\ExplSyntaxOff

\initformat{\MakeUppercase} % initialize

\begin{document}

\init{abc}

\initformat{\textsc}

\init{abc}

\end{document}

在此处输入图片描述

如果首字母缩写后面跟着句点,而您想删除后面的句点,您可以检查它并做出决定。在我使用的示例中,\xspaceskip效果更加明显。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\init}{m}
 {
  \tanh_init:n { #1 }
 }
\NewDocumentCommand{\initformat}{m}
 {
  \cs_set_eq:NN \tanh_init_format:n #1
 }

\seq_new:N \l_tanh_init_seq

\cs_new_protected:Nn \tanh_init:n
 {
  \seq_set_split:Nnn \l_tanh_init_seq { } { #1 }
  \tanh_init_format:n { \seq_use:Nn \l_tanh_init_seq { . } }
  \tanh_init_period:
 }
\cs_new_protected:Nn \tanh_init_period:
 {
  \peek_charcode:NTF . { \@ } { \tanh_init_format:n { . } \@ }
 }
\ExplSyntaxOff

\xspaceskip=20pt

\initformat{\MakeUppercase} % initialize

\begin{document}

\init{abc} whatever

\init{abc}. A period!

\initformat{\textsc}

\init{abc} whatever

\init{abc}. A period!

\end{document}

在此处输入图片描述

如果要保留字距调整,需要事先进行测试.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\init}{m}
 {
  \tanh_init:n { #1 }
 }
\NewDocumentCommand{\initformat}{m}
 {
  \cs_set_eq:NN \tanh_init_format:n #1
 }

\seq_new:N \l_tanh_init_seq

\cs_new_protected:Nn \tanh_init:n
 {
  \seq_set_split:Nnn \l_tanh_init_seq { } { #1 }
  \tanh_init_period:
 }
\cs_new_protected:Nn \tanh_init_period:
 {
  \peek_charcode_remove:NTF .
   {
    \tanh_init_format:n { \seq_use:Nn \l_tanh_init_seq { . } . } \spacefactor\sfcode`.~ 
   }
   {
    \tanh_init_format:n { \seq_use:Nn \l_tanh_init_seq { . } . } \@
   }
 }
\ExplSyntaxOff

\xspaceskip=20pt

\initformat{\MakeUppercase} % initialize

\begin{document}

\init{abp} whatever

\init{abp}. A period!

\initformat{\textsc}

\init{abp} whatever

\init{abp}. A period!

\textsc{a.b.p.} A period!

\end{document}

在此处输入图片描述

答案2

一种方法是:

\documentclass{article}

\begin{document}
\newcommand{\init}[1]{%
  \let\nextinit=\relax
  \if\relax\noexpand#1\relax\else#1.\let\nextinit=\init\fi\nextinit}

\init IBM\relax{} is an abbreviation, as is
\init GNU\relax.  What is \init SPECTRE{}?
\end{document}

\init现在被定义为一个接受单个参数的函数。因此,在 中\init IBM,首先,只有 才是I的参数\init。这个想法是\init检查其参数是否等于\relax。如果是,它什么也不做并停止。如果不是,那么它会打印参数加上 .,然后复制自身。因此它会继续,直到遇到\relax。它也会停止在{}(即使严格来说,这并不是\relax,但很好)。

您还可以尝试使用其他停止标准,例如特殊字符\@ifnextchar请参阅理解 \@ifnextchar

相关内容