在Emacs中重新定义“句子”?(单个空格分隔句子,但忽略缩写词)

17

我想在Emacs中能够通过句子进行导航(M-a, M-e)。问题是:默认情况下,Emacs期望每个句子之间有两个空格,而我习惯于只放一个空格。当然,可以关闭该设置,以允许只用一个空格分隔句子,方法如下:

(setq sentence-end-double-space nil)   

然而,Emacs在缩写后的句点(".")后认为句子已经结束了,例如在类似"...一个奇怪的命令,例如foo..."之后。

所以,有没有一种方法可以定义sentence-end变量,让其将[.!?]视为标志句子的结尾,当且仅当接下来的是一个或多个空格,后面跟着一个大写字母[A-Z]?

还有...如果后面跟着零个或多个空格,再跟着一个"\", 那么也允许[.!?]标记句子的结尾吗?[这种情况的原因是为了编写LaTeX代码:其中一个句子后面跟着一个像\footnote{}这样的LaTeX命令,例如"...所以我们可以看到该点已被证明。\footnote{至少在某个替代的世界里。}"]

我尝试过对sentence-end的定义进行调整,并得出了以下内容:

(setq sentence-end "[.!?][]'\")}]*\\(\\$\\|[ ]+[A-Z]\\|[ ]+[A-Z]\\| \\)[
 ;]*")

但是这似乎完全没有用。

有什么建议吗?


2
博士Shivago。例如加拿大。圣乔治。 - Svante
啊,对了。我没有想到那个。我想除了在句子之间实际放置两个空格以区分之外,没有其他的方法了。但是在我写的大部分内容中,我不使用像“Dr.”或“St.”这样的称号,而且我通常不会在“例如”之后列出专有名词。因此,如果我能弄清楚如何定义它,它仍然可以在99%的情况下工作。[此外,我仍然好奇如何允许反斜杠LaTeX命令不干扰句子结尾。] - emacsomancer
@Svante!并不是每个人都像你一样拼写他们的名字。它是Zhivago。天啊。 - Cheeso
顺便问一下,在Emacs中现有的sentence-end值是否也适用于印度现代语言或梵文,以通常在天城体中输入的方式? 如果不行,我们能否提出改进意见? - imz -- Ivan Zakharyaschev
@imz:传统上,天城文使用类似直线的标记来表示标点符号:一个单独的|通常模糊地像逗号或分号,而双||则是句号(有时仅使用|,然后像句号)。然而,现代印地语等即使使用天城文书写也经常使用“,”、“。”作为标点符号。对于Emacs,现代方式可以与当前定义一起使用(只要用两个空格分隔句子);传统符号需要对当前Emacs定义进行一些添加。 - emacsomancer
@BeSlayed:谢谢,我明白了。所以现在Emacs中的这个函数在不使用包的情况下不能很好地国际化。 - imz -- Ivan Zakharyaschev
1个回答

4
我认为句子结尾并不能做你需要的事情。你真正需要的是前瞻正则表达式,但Emacs不支持它们。
你可以自己编写函数来实现你的需求。虽然我不是很理解你所有的要求,但以下是一个起点:
(defun my-next-sentence ()
"Move point forward to the next sentence.
Start by moving to the next period, question mark or exclamation.
If this punctuation is followed by one or more whitespace
characters followed by a capital letter, or a '\', stop there. If
not, assume we're at an abbreviation of some sort and move to the
next potential sentence end"
  (interactive)
  (re-search-forward "[.?!]")
  (if (looking-at "[    \n]+[A-Z]\\|\\\\")
      nil
    (my-next-sentence)))

(defun my-last-sentence ()
  (interactive)
  (re-search-backward "[.?!][   \n]+[A-Z]\\|\\.\\\\" nil t)
  (forward-char))

大部分的调整需要集中在查看正则表达式上,以确保它能够满足所有可能的句子结束条件。如果它发现正常的句子,则可以不做任何修改;如果你处于LaTeX命令状态,则可以将光标移动到下一个{之后;或者根据需要进行其他修改。
一旦完成了这些调整,就可以将函数绑定到M-a和M-e键上,使用模式钩子即可,除非你想在每个模式中都使用它们。

谢谢。我没有想到可以使用单独定义的正则表达式函数来实现它。你建议的函数似乎基本上都能工作 - 我还在稍微尝试一下(由于某种原因,反向函数似乎比正向函数更难以正确实现)。 - emacsomancer
1
是的,re-search-forward 会将您放在匹配项的末尾,这正是您想要到达两个句子之间的分隔符。re-search-backward 会将您放在匹配项的开头,这可能需要一些调整。我使用了(forward-char),但如果您开始为第一个匹配项开发更复杂的正则表达式,您可能会更幸运地将其替换为(goto-char(match-end))。 - Tyler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接