isearch-mb: 在 minibuffer 中编辑 isearch query

现今流行的搜索工具如 swiper、helm-swoop 等,设计都是在 minibuffer 中编辑搜索 query,非常方便。相比之下,isearch 的默认行为就比较差:

  • 只有输入和退格可以用。
  • 在这个时候按一个非 isearch 的命令就会退出 isearch。这点是最恼人的。
  • 按一下 M-e 才能自由编辑搜索 query。
  • 在编辑时 buffer 内的匹配不会更新。

昨天看到一个 isearch-mb,给 isearch 带来了和 swiper、helm-swoop 一样的体验:直接在 minibuffer 中编辑 query,buffer 的匹配随之更新。

其实本来打算自己写一个一样的东西了 :rofl: 真是想啥有啥

2 个赞

可以换掉 consult 吗

:+1:这个看起来不错,使用minibuffer 也许就能解决了我用 i-search 时 emacs-rime 不会自动切换输入法的问题。

大部分时候 isearch 肯定是够了。

isearch 是 buffer 内搜索,consult-line 是过滤 buffer 内的行,所以 isearch 可以搜索多行(按 C-q C-j 就可以在 search query 里输入换行符),consult 没有这个能力。

另一方面,consult-line 是用 Emacs 的 completion style 那一套来过滤,不是正则,所以配合 orderless 之类的包,可以做到模糊匹配。isearch 最多就只能用正则,很难做到类似的效果。

所以最终还是看需求。我个人觉得 99% 的场合,isearch 都够了。

1 个赞

写了一个配合 isearch-mb 的 advice,可以在 prompt 里显示当前是不是 case-fold search:

(define-advice isearch-mb--update-prompt (:around (fn &rest _) show-case-fold-info)
    "Show case fold info in the prompt."
    (cl-letf* ((isearch--describe-regexp-mode-orig
                (symbol-function 'isearch--describe-regexp-mode))
               ((symbol-function 'isearch--describe-regexp-mode)
                (lambda (regexp-function &optional space-before)
                  (concat (if isearch-case-fold-search "[Case Fold] " "")
                          (funcall isearch--describe-regexp-mode-orig
                                   regexp-function space-before)))))
      (funcall fn _)))

效果:

image

在这个时候按一个非 isearch 的命令就会退出 isearch

这个是刚需,已经加入了自己的Emacs配置中,好用。

1 个赞

isearch 的默认行为不就是会退出吗?我按一下 C-n / C-p 移动光标就退出了。

最近用了这个包以后,仔细研究了下 Emacs 自带的查找替换。

Emacs 的 query-replace 最大的问题也是敲一个不在 query-replace-map 里面的键就会退出,非常烦人。写了一个补丁,使得这个时候的行为变成打开帮助:

(define-advice perform-replace (:around (fn &rest args) dont-exit-on-anykey)
  "Don't exit replace for anykey that's not in `query-replace-map'."
  (cl-letf* ((lookup-key-orig
              (symbol-function 'lookup-key))
             ((symbol-function 'lookup-key)
              (lambda (map key &optional accept-default)
                (or (apply lookup-key-orig map key accept-default)
                    (when (eq map query-replace-map) 'help)))))
    (apply fn args)))

想把它改成「什么都不干」还是比较困难的(至少我研究之后觉得不可能)。我觉得打开帮助还算是个比较好的行为。

cc @manateelazycat 感觉你应该需要这个。

另外,自己撸了一个更好看的帮助信息:

(setq query-replace-help
      "<Replace>
[y/SPC] replace                         [!] replace all remaining
[.] replace only one                    [,] replace and not move to next
<Exit>
[q/RET] exit
<Move>
[n/DEL] next          [^] prev          [C-l] recenter
<Undo>
[u] undo previous                       [U] undo all
<Edit>
[C-r] recursive edit                    [\\[exit-recursive-edit]]: exit recursive edit
[C-w]: delete match and recursive edit  [E]: edit the replacement string.
<Multi-file replace>
[Y]: replace all in remaining buffers   [N]: skip to the next buffer")

在替换的过程中按 ? 就可以看到了。

1 个赞

试了下,isearch-mb 似乎也不能直接输入中文,isearch 至少还能 M-e 编辑中文

是的,确实不行。我现在还是用isearch,不折腾了。我搜索中文用的比较少。

@wenpin @aqua0210 我特地装了个 emacs-rime,用 rime 或外部输入法都正常啊,你们为啥不能用呢 :rofl:

image

rime 可以。最近用了 pyim, pyim 不行。

我一般用pinyin搜中文。。。。

pinyin 搜索中文,一定要安装 pyim 的 吧? 用 Emacs-rime 习惯了,不知道有没可能和 emacs-rime 集成?

有另外一个包,可以实现拼音首字母搜索,忘记叫什么名字了,可以找找, pyim 不需要启用就可以实现 pinyin 搜索中文, 和 emacs-rime 没冲突

pyim 自带和 librime 的集成方案,没有 emacs-rime 功能多,可以看看 readme 了解一下。

多谢,之前也看过这个安装说明,就是觉得 librime 的安装和配置又是要折腾。回头准备试试直接使用 pyim 的拼音输入法,依赖外部是挺烦的。

原来是我配置姿势不对,之前只是绑定了快捷键,没有启动isearch-mb-mode,可以直接输入中文。多谢提醒, isearch-mb 好用。

1 个赞
;; https://emacs.stackexchange.com/questions/80484/query-replace-ignore-events-not-binded-in-query-replace-map
(defvar vmacs-do-nothing-map
  (let ((map (make-keymap)))
    (set-char-table-range (nth 1 map) t 'ignore)
    map))
(set-keymap-parent query-replace-map vmacs-do-nothing-map)

这里有解决方案