对整个单词进行宏操作(纯 TeX)

对整个单词进行宏操作(纯 TeX)

我花了大量时间在参考资料和论坛中寻找我在此提出的问题的答案。

我想编写一个宏,将单词作为参数,而无需使用括号来通知这一点。这将是一个智能宏,可以识别什么应该是参数的组成部分,逐个标记地构造它,直到找到不合适的候选者(在完成宏本身后将被完整替换)。例如

\def\km#1{% definition: only accept numbers: writes the unit after the subsequent integer word (parameter)%}
\def\mathstyle#1{% definition: accept anything except point and space: put parameter in mathmode (assumes that is called in "text mode" for simplification)%}
% usage
The radius of the Earth is about \km 6300. %%
%% *\km 6300.* expands to 6300 $km$.
The distance between \mathstyle Point-A to \mathstyle Point-B is \km 20 assume that the Earth is plain.
%% puts Point-A and Point-B between math shifts

简而言之,为了实现这一点,据称我需要逐个检查字符并调用处理宏,直到它获取无法识别的标记。

问题是:在许多情况下,TeX 会忽略宏后的空格。因此,我无法创建处理空格的宏(将所有用空格分隔的单词连接起来)。

我该如何修复?现在如何销毁宏后的空格?

答案1

我不确定我是否理解了这个问题(“现在如何销毁宏后的空格?”这个问题似乎与上面的上下文无关,也许举个例子会很有启发)。要回答获取单个单词作为参数的问题,您可以使用扫描标记逐个标记\futurelet并测试是否出现字母

\protected\def\getword#1{%
    \begingroup \toks0{}\toks1{#1}%
    \futurelet\next\getwordA
}
\def\getwordA{\ifcat A\noexpand\next \expandafter\getwordB \else \expandafter\getwordC \fi}
\def\getwordB#1{\toks0\expandafter{\the\toks0 #1}\futurelet\next\getwordA}
\def\getwordC{\edef\tmp{\endgroup \the\toks1{\the\toks0}}\tmp}

\def\textbf#1{{\bf#1}} \def\textit#1{{\it#1\/}} % demo

\getword\textbf Foo bar
{\getword\textit baz} fu

\bye

通过添加一些额外的检查,可以轻松允许破折号、下划线等。

输出

答案2

有一些病态情况需要测试,例如如何处理中的小数点\km。幸运的是,逻辑可以构建到令牌循环中,并且tokcycle可以从纯文本中调用。

\input tokcycle.tex
\def\aborttoks{\tcpush{\empty\endtokcycraw}}
\newif\ifdotless
\xtokcycleenvironment\km
 {\tctestifnum{`##1<`0}{%
  \ifdotless\ifx.##1\addcytoks{##1}\dotlessfalse
  \else\aborttoks\fi\else\tcpush{##1}\aborttoks\fi}{%
  \tctestifnum{`##1>`9}{\aborttoks}{\addcytoks{##1}}}}
 {\tcpushgroup{##1}\aborttoks}
 {\tcpush{##1}\aborttoks}
 {\tcpush{##1}\aborttoks}
 {\dotlesstrue}
 {\addcytoks{\kern2pt km}}

Testing \km3., \km 4000 and \km 2.3. Next sentence.

\bye

在此处输入图片描述

答案3

如果您可以使用 e-TeX 扩展(即pdftex),您就可以利用expl3

\input expl3-generic

\ExplSyntaxOn

\cs_new_protected:Npn \mathstyle
 {
  \peek_regex_replace_once:nnF
   { (.*?)(\.|\s) } % search anything up to a period or space
   { \c{ensuremath}\cB\{\1\cE\}\2 } % replace with \ensuremath{<tokens>}<period or space>
   {} % do nothing if no match
 }
\cs_new_protected:Npn \km
 {
  \peek_regex_replace_once:nnF
   { ([[:digit:]]*) } 
   { \c{ensuremath}\cB\{\1\c{kilometers}\cE\} } % replace
   {} % do nothing if no match
 }

\cs_new_protected:Npn \ensuremath #1
 {
  \mode_if_math:TF { #1 } { $#1$ }
 }

\cs_new_protected:Npn \kilometers { \,\rm km }

\ExplSyntaxOff

The distance between \mathstyle {\rm Point-}A to $\mathstyle {\rm Point-}B$ is \km 20, assume 
that the Earth is plain and no wider than $\km 100000$.

\bye

如您所见,宏在文本和数学模式下都有效。

在此处输入图片描述

相关内容