我正在尝试实现 LaTeX 命令\text{}
,使数学模式下的文本表现得就像在数学模式之外一样。
我目前的尝试如下。
\def\text#1{\begingroup\rm\testing#1\endtest}
{\escapechar=-1\xdef\endtest{\string\\endtest}}
\def\testing#1#2{\ifx#2\endtest\let\next=\endgroup\else\let\next=\testing\fi%
{\catcode`\|=10\ifcat#1|\hskip.5em\else#1\fi}\next #2}
这至少有两个缺点:首先,它会\endtest
在文本后产生;其次,文本中没有空格。
例如,
\text{example haha}
给出
examplehaha\endtest.
我没有什么办法可以摆脱它\endtest
在文本中并留下空间。
对于像我这样的新手来说,任何帮助或参考都非常感谢。提前致谢。
答案1
很简单,你只需要使用
\hbox{hello world}
在amsmath
(或更确切地说amstext
)中\text
被定义为使用\mathchoice
并使用不同大小的文本是下标等,但是纯文本没有真正的字体大小更改命令,因此默认情况下,您无法执行任何类似的操作。如果您限制为,\rm
那么该字体在中设置为不同的大小,\fam0
因此您可以执行
\def\textrm#1{\mathchoice
{\hbox{\the\textfont0 #1}}
{\hbox{\the\textfont0 #1}}
{\hbox{\the\scriptfont0 #1}}
{\hbox{\the\scriptscriptfont0 #1}}}
$$\textrm{one two} x^{\textrm{one two}^{\textrm{one two}}}$$
\bye
答案2
您可以使用opmac
(如果您坚持使用纯 TeX,我推荐您使用):
\input opmac
\def\text#1{%
\relax
\ifmmode
\mathchoice
{\hbox{#1}}
{\hbox{#1}}
{\hbox{\typoscale[700/]\relax#1}}
{\hbox{\typoscale[500/]\relax#1}}%
\else
\hbox{#1}%
\fi
}
$$
a\text{a}_{a\text{a}_{a\text{a}}}
$$
$$
a+b=b+a\text{ is a {\it nice\/} property}
$$
$$
\scriptstyle a+b=b+a\text{ is a {\it nice\/} property}
$$
$$
\scriptscriptstyle a+b=b+a\text{ is a {\it nice\/} property}
$$
\bye
只是为了好玩,让我尝试描述一下你的宏的作用。
\def\text#1{\begingroup\rm\testing#1\endtest}
{\escapechar=-1\xdef\endtest{\string\\endtest}}
\def\testing#1#2{\ifx#2\endtest\let\next=\endgroup\else\let\next=\testing\fi%
{\catcode`\|=10\ifcat#1|\hskip.5em\else#1\fi}\next #2}
第一个\text
被定义为吸收其参数并返回标记列表
\begingroup\rm\testing<argument>\endtesting
该宏\testing
被定义为具有两个参数。如果第二个参数是\endtest
,则控制序列\next
被定义为,\endgroup
否则被定义为\testing
,这将启动递归。然后
{\catcode`\|=10\ifcat#1|\hskip.5em\else#1\fi}
完成,其中#1
代表 之后的第一个标记(或括号组的内容)\testing
。测试\ifcat#1|
将不是如果是空格则成功,#1
原因有两个:当 TeX 寻找未分隔的参数时,空格会被忽略,#1
因此绝不是空格标记;第二个原因,当 是类别代码 12 的单个标记时,测试将成功,这是定义时#1
的类别代码。|
因此,如果后面跟着诸如 (catcode 12) 之类的字符.
(并且忽略该字符),则会得到一个空格,否则,如果该字符是字母,则会得到该字符。如果#1
是括号组的内容,那么,任何事情都可能发生。\next
执行 Finally,然后#2
重新插入。这就是“endtest”出现在末尾的原因。
回想一下,当一个论点被吸收时,类别代码会被冻结,因此设置\catcode`\|=10
根本不会执行任何操作。
通过添加两个终止符,可以获得没有“终止”问题的递归。
% generic terminators
\def\TerminatorA{\TerminatorA}
\def\TerminatorB{\TerminatorB}
\def\boldenas#1{\boldenasRecurse#1\TerminatorA\TerminatorB}
\def\boldenasRecurse#1#2#3\TerminatorB{%
\boldenasDo{#1}%
\ifx#2\TerminatorA
\let\next\boldenasEnd
\else
\let\next\boldenasRecurse
\fi
\next#2#3\TerminatorB
}
\def\boldenasDo#1{%
\ifx #1a%
{\bf a}%
\else
#1%
\fi
}
\def\boldenasEnd#1\TerminatorB{}
\boldenas{abracadabra}
\bye
这对于空值来说并不安全#1
(毕竟我们是严格的普通 TeX 用户)。空格将被吞噬,原因我之前解释过,而支撑组将产生混乱。但是,嘿,我们在做理论!
请注意,\let
可以避免以下指令:
% generic terminators
\def\TerminatorA{\TerminatorA}
\def\TerminatorB{\TerminatorB}
% syntactic sugar
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
\def\boldenas#1{\boldenasRecurse#1\TerminatorA\TerminatorB}
\def\boldenasRecurse#1#2#3\TerminatorB{%
\boldenasDo{#1}%
\ifx#2\TerminatorA
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi
\boldenasEnd\boldenasRecurse#2#3\TerminatorB
}
\def\boldenasDo#1{%
\ifx #1a%
{\bf a}%
\else
#1%
\fi
}
\def\boldenasEnd#1\TerminatorB{}
\boldenas{abracadabra}
\bye