Appendix A the-the 函数

有时在编写文本时会不小心重复输入单词——比如本句开头的“you you”。我发现自己最常重复输入的是“the”,因此将这个检测重复单词的函数命名为 the-the

第一步,你可以使用下面的正则表达式搜索重复单词:

\\(\\w+[ \t\n]+\\)\\1

该正则表达式匹配一个或多个单词构成字符,后跟一个或多个空格、制表符或换行符。但它无法检测位于不同行的重复单词,因为第一个单词以行尾结束,第二个单词以空格结束,二者结尾不同。(有关正则表达式的更多信息,参见 Regular Expression Searches,以及 Syntax of Regular Expressions in The GNU Emacs ManualRegular Expressions in The GNU Emacs Lisp Reference Manual。)

你可以尝试仅搜索重复的单词构成字符,但这并不可行,因为该模式会误判类似“with the”中连续出现的“th”。

另一种可行的正则表达式是搜索单词构成字符后跟非单词构成字符并重复的组合。其中 ‘\\w+ 匹配一个或多个单词构成字符,‘\\W* 匹配零个或多个非单词构成字符。

\\(\\(\\w+\\)\\W*\\)\\1

该方式同样不适用。

下面是我实际使用的模式。它并不完美,但足够实用。 ‘\\b 匹配位于单词开头或结尾的空字符串;‘[^@ \n\t]+ 匹配一个或多个 @-符号、空格、换行符或制表符的字符。

\\b\\([^@ \n\t]+\\)[ \n\t]+\\1\\b

可以编写更复杂的表达式,但我发现该表达式已足够好用,因此一直沿用。

下面是我在 .emacs 文件中配置的 the-the 函数,同时附带一个便捷的全局按键绑定:

(defun the-the ()
  "向前搜索重复的单词。"
  (interactive)
  (message "Searching for for duplicated words ...")
  (push-mark)
  ;; 该正则表达式并不完美
  ;; 但整体效果尚可:
  (if (re-search-forward
       "\\b\\([^@ \n\t]+\\)[ \n\t]+\\1\\b" nil 'move)
      (message "Found duplicated word.")
    (message "End of buffer")))

;; 将 'the-the' 绑定到 C-c \
(keymap-global-set "C-c \\" 'the-the)

下面是测试文本:

one two two three four five
five six seven

你可以将上面展示的其他正则表达式替换到函数定义中,并在该文本列表上逐一测试。