【傻瓜教程】Emacs 定身术之 consult+embark+wgrep 跨文件批量搜索替换

以将两个文件 test.eltest.org 中的文本 suliveevil-test 替换为 my/test 举例说明:

跨文件批量搜索替换

打开 Emacs,按以下步骤操作:

  1. C-c r e 调用 consult-grep 并输入 suliveevil-test 进行搜索

  2. H-o 调用 embark-export 将结果从 minibuffer 导出到 buffer(grep-mode)

  3. C-c C-q 调用 wgrep-change-to-wgrep-mode 将 buffer 的模式从 grep-mode 切换为 wgrep-mode

  4. M-% 调用 query-replace 进行批量替换,此时输入要被替换的内容 suliveevil-test回车,然后输入要替换为的内容 my/test回车

  5. 依次按下 yn 对每个替换选项进行确认,或按下 ! 对全部结果进行替换。

  6. 替换结束后,C-c C-c 调用 wgrep-finish-edit 结束编辑。

文件

user-emacs-directory~/emacs.d/~/.config/emacs/) 下的 test.eltest.org

  • test.el
suliveevil-test-1
suliveevil-test-2
  • test.org
suliveevil-test-3
suliveevil-test-4

操作后的文件:

  • test.el
my/test-1
my/test-2
  • test.org
my/test-3
my/test-4

最小相关配置

(use-package consult
  :bind ("C-c r e" . consult-grep)
)

(use-package embark
  :bind
  (
   :map minibuffer-mode-map
   ("H-o" . embark-export)
   )
  )

(use-package embark-consult
  ;; :hook (embark-collect-mode . consult-preview-at-point-mode)
  )

(use-package wgrep
  :bind
  (
   :map grep-mode-map
   ("C-c C-q" . wgrep-change-to-wgrep-mode)
   )
  )

视频演示

相关帖子

6 个赞

前两步依赖的 consult 和 embark-consult 可以用 Emacs 自带的 grep-find 命令代替。

第二步依赖的 embark(embark-export) 暂时不清楚有没有 Emacs 内置命令可以替换。

第三步依赖的 wgrep 是核心,应该还没有可以替换的插件。

搜索时输入一次query,替换时又输入一次query,这才是你应该优化的步骤。

color-rg 操作都比这些快啊

1 个赞

刚开始用起来,还没仔细研究。

不过重复步骤的问题在我看来不算核心问题,用 symbol-overlay 然后 save-symbol,再粘贴两次也是可以的,没必要为了这一步的简化单独写个函数。

之前安装了但没仔细研究,最近重写了几遍自己的配置,还没安装 color-rg :rofl:

你说的所有功能 color-rg 都有, 而且是一个插件就搞定了,不用像你写的那样来回几个插件相互衔接才能工作。

2 个赞

其实没必要绕embark一圈。我用的是和 color-rg 类似的 rg ,搜索出结果后直接按 e 就可以进入编辑模式了。

1 个赞

主要是 git submodule 偶尔抽风搞得我有点火大,就想着一点点根据已经安装的 elpa/melpa 插件重新梳理自己的配置。

git submodule 时不时自动切到 HEAD 分支、时不时自动把 submodule 文件夹下的文件都删除掉……

这么神奇吗?感觉错过了一个亿。

我是安装了 helpful 作者的 deadgrep,就没再看 rg 的功能 :rofl:

deadgrep 也有个deadgrep-edit-mode ,功能应该类似。

1 个赞

:joy: 是我浅尝辄止了。 前两天刚装上 wgrep,正赶上它两年来首次更新,就想着把它用起来,也就没想着别的 grep 插件也有类似高级功能。

:joy:我也是才知道原来 wgrep 居然有个单独的包

猛一看这个名字我还以为和 wdired 一样是内置插件,后来看到它近两年没更新就不太想用它,没想到刚装上还没用起来它就更新了,所以我就照着坛里几个帖子把 wgrep 用了起来。

如果不是你,我真没注意原来 rg 和 deadgrep 已经集成了这些功能。

我再试试 color-rg,多搞几套方案。 :stuck_out_tongue_closed_eyes:

我想起来为啥我没第一时间研究 deadgrep 是不是有高级功能了:我的 test.eltest.org 都 gitignore 了,deadgrep 默认不搜索被 ignore 的文件……

回头我看看有没有切换搜索被 ignore 的文件的功能。

我挺喜欢deadgrep的,因为它的界面上端把查询条件都做成了交互式,可以很方便的切换,文件目录、case insensitive 之类的… 唯一缺点是界面太素了 :joy:

加张图:上面是交互式的,任意更改。modeline圆圈里 == 其实是指示查询状态的,一直在滚动。

2 个赞

关于二次输入查询语句的问题:

  1. 使用consult内置的查询当前光标所在symbol的功能,但不够智能。
  2. 使用 更通用的xxx-thing-at-point 的方案。自动把xx-at-point/或region 作为查询词,任意输入的时候会自动抹掉自选词,输入自己的词。

方案二挺牛掰的。

更正:会错意了,以上无法解决二次输入问题。

方案二的思路确实很智能,非常棒的思路,也可以用在别的场景里(比如翻译单词/句子/段落、选区)。

是的,非常舒服,因为那些自动选择到minibuffer里的的文字有自删功能。只要不是指定command, 就会自动销毁。

另外说到替换,还有个功能很棒:project-query-replace-regexp。 比如emacs.d有很多子目录子文件,我有个自定义命令叫custom-command分散到各个文件里, 想统一换成my-custom-command, 这个命令可以很方便替换所有。

我很不解的一点就是 Emacs 自己的 rename-visited-file 居然没有自动填写当前文件名+文件扩展名并提前选中文件名的功能,而是默认完全从零重命名。

macOS 的访达只需要按回车就自动选中文件名(开启了显示文件扩展名功能),这一点非常人性化。