在 emacs 中,如何替换文本块中的所有重音符号?

In emacs, how would I replace all accents in a block of text?

假设我有:

“有恩典是一回事,报告恩典是另一回事。如果需要的话,并不是所有感谢你的人都会在以后回报你的感激之情。感恩很容易,记住这些好处似乎没有什么比这更难的了。”

但是我想要

“得恩是一回事,报恩又是一回事。并非所有对你的帮助表示感谢的人,如果需要,都会在以后回报你。感恩恩人容易,我看没有什么比缅怀恩人更难的了。”

即â ä -> ā 等 ëê -> ē 等

我在想一个大键盘宏来做大量的搜索和替换,但是有更好的方法吗?

在许多情况下,它节省了大量编写 Emacs lisp 函数的时间,而不是存储 kbd-macros 等。Emacs 带有出色的调试工具。例如,在您的示例中使用以下解决方案调用 M-x edebug-eval-top-level-form RET

(defun accent-replace ()
  "Does what I want"
  (interactive "*")
  (dolist (ele (list ?â ?ä ?ê ?ë ?î ?ô))
    (setq elt (char-to-string ele))
    (goto-char (point-min))
    (while (search-forward elt nil t 1)
      (replace-match
       (char-to-string
    (pcase ele
      (`?â ?ā)
      (`?ä ?ā)
      (`?ê ?ē)
      (`?ë ?ē)
      (`?î ?ī)
      (`?ô ?ō)))))))

受到评论的启发,我想出了这个交互式命令:

(defun tr (from to beg end)
  "Replace each character in FROM with the character at the same position in TO.
Operates from BEG to END, or within the marked region if called interactively.

If TO is shorter than FROM, any characters in FROM beyond the length of TO are
just deleted."
  (interactive "sTranslate from: \nsTranslate to: \nr")
  (goto-char beg)
  (setq end (copy-marker end))
  (let ((regexp (regexp-opt (mapcar 'string from))))
    (while (search-forward-regexp regexp end t)
      (let* ((index (cl-search (match-string 0) from))
             (replace-with (if (> (1+ index) (length to))
                               ""
                             (substring to index (1+ index)))))
        (setf (buffer-substring (match-beginning 0) (match-end 0)) replace-with)))))

标记包含文本的区域,调用M-x tr,将âäëê作为第一个字符串传递,将āāēē作为第二个字符串传递。