能否让宏在新的句子开头给出不同的结果?假设我希望宏“\secname”在新的句子开头写“Section”,在其他地方写“section”。我该怎么做?
答案1
您可以将“句子结尾”字符的 \sfcode 设置为不同的值并进行测试:
\documentclass[10pt]{report}
\sfcode`\.=1001
\sfcode`\?=1001
\sfcode`\!=1001
\sfcode`\:=1001
\newcommand\secname{\ifnum\spacefactor=1001 Secname\else secname\fi}
\begin{document}
abc. \secname\ is \secname.
e.g.\@ \secname
\end{document}
\nonfrenchspacing 也设置 \sfcodes。在这种情况下,您可以使用类似下面的命令:
\documentclass[10pt]{report}
\nonfrenchspacing
\newcommand\secname{\ifnum\spacefactor>1900 Secname\else secname\fi}
\begin{document}
abc. \secname\ is \secname.
abc: \secname, \secname.
e.g.\@ \secname
\end{document}
答案2
最简单的方法是定义两个宏:
\def\secname{section}
\def\Secname{Section}
确定句子边界是一项非常困难的任务,也是计算语言学中最热门的话题之一。要正确做到这一点,您需要确定在《神秘博士》中,“Dr.”后面的句号不是句子的结尾,因此您需要解析所有缩写,当您想测试下一个字母是否以大写字母开头时,请考虑我们使用的所有拉丁缩写。
答案3
在 Ulrike 发布使用 的漂亮答案之前\spacefactor
,我曾认为如果不重新定义 ,在 TeX 中这是不可能的.
。 只是为了完整性:这是我的答案,它确实重新定义.
(在将其激活之后,这可能不是一个好主意)。 请注意,您不必\@
在 Ulrike 的解决方案中使用 as 。
\documentclass{article}
\let\period.
\catcode`.=\active
\let\qwe\relax
\futurelet\myspace{ }
\newcommand.{\period\futurelet\nextchar\testspace}
\newcommand\testspace{\ifx\nextchar\myspace\expandafter\eatspace\expandafter.\fi}
\def\eatspace. { \futurelet\nextchar\testsec}
\newcommand\testsec{\ifx\nextchar\secname\def\qwe{ }\fi}
\newcommand\secname{\ifx\qwe\relax section\else Section\let\qwe\relax\fi}
\begin{document}
abc. \secname\ is \secname.
abc: \secname, e.g.\ \secname.
\end{document}
是的,这看起来好像我试图让它尽可能地晦涩难懂。两个有趣的点:1. 请注意\myspace
(\space
不起作用!)的定义。2. 我没有设法使用 LaTeX 来\ifnextchar
测试下一个字符是否是空格,所以我使用了\futurelet
。
答案4
这是一个新的答案,部分灵感来自最近的查询在句子开头表现不同的宏,该查询因与当前查询重复而被关闭(直到今天我才意识到这一点)。
假设作者定义了两个宏\agt
,分别称为 ,输出字符串“the agent”,和\Agt
,输出“The agent”(大写“T”)。此外,我们假设作者希望自动\agt
表现为\Agt
如果- 和除非--\agt
出现在句子开头。(出于某种原因,作者无法根据需要手动替换\agt
... \Agt
)
假设我们可以放心地忽略诸如Mr. \agt
或Mrs. \agt
之类的情况,因为它们不太可能出现在实际文档中,那么以下基于 LuaLaTeX 的解决方案可能会引起人们的兴趣。它不对\sfcode
各种潜在的句末标点符号的 -status 做出任何假设,并且无论\frenchspacing
或\nonfrenchspacing
是否有效,它都可以正常工作。它的工作假设是,在以下两种情况下,\agt
应该将 更改为:\Agt
\agt
出现在输入行的开头。行首和 之间的空格\agt
是可以的。或者,\agt
前面是?
、!
、 或.
(英语中三个主要的句末标点符号),后面是一个或多个空格字符。(因此,诸如.\agt
和 的情况?\agt
不会被修改。)当然,如果您的文档所用的语言具有不同的句末标点符号,请随意修改下面显示的
[...]
第二个语句中所括的字符列表。gsub
另外:我写这个答案时假设人们使用的编辑器通过插入“软”换行符来“重新排列”段落。(这是我使用的所有编辑软件的行为......)但是,正如@jfbu 在评论中指出的那样,其他编辑器(显然包括 Emacs - 抱歉,我个人不使用 Emacs)使用了不同的方法,即,他们通过插入“硬”换行符来重新排列段落,实际上将段落存储为一系列单独的字符串。这种方法显然增加了某些实例\agt
出现在行首的风险,这反过来又使所提出的方法变得不那么有吸引力。唉。恐怕我不知道该给出什么建议。
那么,这里就是一个 MWE。
% !TEX TS-program = lualatex
\documentclass{article}
\def\agt{the agent}
\def\Agt{The agent}
\usepackage{luacode}
\begin{luacode}
function agt_to_Agt ( s )
s = s:gsub ( "^%s-\\agt", "\\Agt" )
return s:gsub ( "([?!.])%s+\\agt" , "%1 \\Agt" )
end
\end{luacode}
\AtBeginDocument{\directlua{luatexbase.add_to_callback
( "process_input_buffer" , agt_to_Agt , "agt_to_Agt" )}}
\begin{document}
\noindent
\agt\ says x. \agt\ shouts Y! \agt\ asks z? \agt\ whispers something
to \agt. \agt\ says the phrase, ``\agt''.
\end{document}