[分享讨论] smart query replace

我现在在尝试从evil切换到emacs键位,给evil里的功能一个一个找替代品。


一般需要替换重复字符的时候,我会用evil的cgn,emacs键位下用query-replace代替。但是手动输入from-stringto-string有点麻烦,我就写了一个小包裹函数。使用方法:

(我绑定到C-x C-q

  1. 选中要替换的地方
  2. C-x C-q
  3. 修改选区(选区会高亮)
  4. 完成后C-x C-q
  5. 进入query replace模式,from-string是原来的字符,to-string是修改后的选区

一开始写的时候比较紧凑,后来不需要了,但是我也懒得改了,反正不复杂,可读性还可以

(defvar smart-query-edit-mode-overlay nil
  "Overlay of region to be replaced.")

(define-minor-mode smart-query-edit-mode
  "Edit region and query replace."
  :lighter "QUERY"
  (if smart-query-edit-mode
      (if (not mark-active)
          (setq smart-query-edit-mode nil)
        (overlay-put
         (setq smart-query-edit-mode-from-string
               (buffer-substring
                (region-beginning)
                (region-end))
               smart-query-edit-mode-overlay
               (make-overlay (region-beginning)
                             (region-end)
                             nil
                             nil
                             t))
         'face '(:inherit highlight)))
    (overlay-put smart-query-edit-mode-overlay
                 'face '(:inherit default))
    (goto-char (overlay-end
                smart-query-edit-mode-overlay))
    (query-replace smart-query-edit-mode-from-string
                   (buffer-substring-no-properties
                    (overlay-start
                     smart-query-edit-mode-overlay)
                    (overlay-end
                     smart-query-edit-mode-overlay)))
    (delete-overlay
     smart-query-edit-mode-overlay)))
2 个赞

解决了 from-string 输入的问题。

to-string 原本也是要输入的,如果输入内容简单,问题不大。如果输入内容复杂,我倾向开一个临时 buffer,优点是:

  • 避免因误删导致 overlay 跟前后字符粘连
  • 方便从别的缓冲区复制内容

如果改成临时 buffer 输入 to-string,那么 from-string 的方式也可以简化:

  1. 选中内容
  2. C-x C-q 调用 query-replace+ 并处于等待输入 to-string,仍然保持原有的 query-replace 风格。此时根据 to-string 内容:
    • 简单:直接输入,回车提交
    • 复杂:按 C-c C-e 进入临时 buffer,输入完,按 C-c C-c 提交

cool,我觉得可以,晚上搞一下

抱歉忘了回了。我后来想了想,你说的其实只需要做一个自动前冲from-string的简单wrapper就好了。to-string的复杂编辑可以用minibuffer-edit搞定。(我记得有一个包是可以弹出一个temp buffer编辑minibuffer的内容)

似乎你是想用anzu的功能?

不完全是吧,重点还是在于替换。