Emacs的补全界面能否支持这种匹配风格?

举例说明, 有如下三个候选项:

aaabbbaaa
aaaccc
aaaddd

输入aa aa后, 等效于aa.*aa, 能唯一匹配第一行, 而不是像orderless或者helm三行都匹配. 他们匹配输入的每个"component" 都是从候选字符串的开头开始, 很不方便.

期望的匹配算法如下:

比如针对第一行的aaabbbaaa, 用户输入aa后空格, 算法就把最左匹配(即候选项开头的aa)去掉不再考虑, 剩余"abbbaaa", 然后用户又输入了第二个aa, 那么就从剩余的abbbaaa中搜索第二个aa, 这样就唯一匹配到了第一行的候选项.

consult rg默认风格不就是吗,虽然我不用,不过它是#分割

我说的不是这个搜索外部文件, 而是emacs内的补全界面, 比如切换buffer, M-x等.

helm 把输入的匹配字符串按空格分割,分成n个独立的部分,每个部分都去匹配候选项。这么做的优点是,可以忽略输入字符的顺序,例如 cc aa 可以匹配 aaaccc,缺点是 aa aa 效果等同于 aa,而你要得效果其实是把 aa aa 转换成 aa.*aa,在 helm 上可以这样实现:

(cl-letf (((symbol-function 'helm-mm-3-get-patterns-internal)
           (lambda (pattern)
             (cl-loop for pat in (helm-mm-split-pattern pattern)
                      collect pat into pats
                      finally return (list (cons 'identity (string-join pats ".*")))))))
  (completing-read "> " '("aaabbbaaa" "aaaccc" "aaaddd")))

image

2 个赞

fuzzy matching 的話, 我推薦 flx. magit 的維護者 @tarsius 認為這是 elisp 包裡唯一聰明的演算法. 我自己也很喜歡用. :yum:

2 个赞

这个 flx 好像作者都不怎么维护了。能用在 Emacs 29 和 Emacs master 上吗? 和 orderless 相比有什么特点呢?

可以用啊~ 依照作者本人的意思. 這個插件已經接近完美了, 所以不需要更新! 我自己也蠻認同的! :thinking:

orderless 可以配置的東西比較多. 但我怎麼配, 都沒有 flx 好用. :joy: 我因為開發 company-fuzzy 用了大概 10 幾種模糊匹配 (包含 completion-styles) 的演算法; 最後總結, flx 比較好用. :rofl:

不過這個本身就很吃使用習慣, 所以自己用的習慣就行! :wink: flx 的特色就是聰明, 但沒有配置選項.

2 个赞

flx 只支持 ido,没法和 vertico 配合。还是需要更新维护的。

还有个新的 hotfuzz, readme 中有 orderless 和 flx 的比对。这个比 orderless 多了排序,不用空格,比较像内置的 flex。

参考:https://github.com/minad/vertico/issues/177#issuecomment-1008182328

1 个赞

我用了很久的 orderless,习惯了。但最近发现左手拇指按太多 Meta 和 空格,开始痛了。所以我打算换掉 orderless。 对 fix 还是比较感兴趣的,可惜我不知道怎么让它在 Emacs 30中支持 completing-read

PS:原来可以通过 fussy 支持 flx:

你可以用 fussy.

現在才看到; 對的, 可以使用 fussy! :wink:

1 个赞

用上了大佬写的 flx-rs + fussy, 体验很好。

1 个赞

现在大家都用 consult 了吗?如果用的 counsel-*,可以使用

(setq ivy-re-builders-alist
        '((t . ivy--regex-plus)))
1 个赞

对, 就是这个意思, 以前用ido的时候, 就把它改成这样了, 感觉非常好用.

你这是怎么做到不高亮中间文本(abbb)的? 中间匹配.*的内容应该也会被高亮吧?

这个插件作者好像是国内的emacs早期玩家. 我看下这个插件能否实现我想要的功能

现在估计很多都用的virtio+consult, 我也是用的这个.

这个匹配算法接口如果遵循emacs内置的completion style, 好像是可以通用的, 类似orderless.

看了下ivy的好像不是这么设计的.

过滤和高亮是各自独立的。

在我电脑上测试了下, 跟预期不一样, 匹配方式依然是老的方式, 可能是我的helm版本太老.

另外, 现在不怎么用helm, 主要用consult了.

@jcs090218 大佬,请问下用 fussy + flx 时下面这个结果是正常的吗?为什么 message-supersede 是第一候选,而不是 message.

image

我的配置:

(use-package fussy
  :custom
  (completion-styles '(fussy basic))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles basic partial-completion))
                                   (eglot (styles fussy basic))))
  (fussy-filter-fn 'fussy-filter-default)
  (fussy-use-cache t)
  :config
  (advice-add 'corfu--capf-wrapper :before 'fussy-wipe-cache)
  (add-hook 'corfu-mode-hook
            (lambda ()
              (setq-local fussy-max-candidate-limit 5000
                          fussy-default-regex-fn 'fussy-pattern-first-letter
                          fussy-prefer-prefix nil))))

目前没法用 flx-rs,因为我这边开开启 flx-rs 时,有些后选会丢失。可能和下面这个 PR有关。

是正常的唷!

(flx-rs-score "message-supersede" "mes")  ; (220 0 1 8)
(flx-rs-score "message" "mes")            ; (214 0 1 2)

flx 的首字比重比較高.

[me]ssage-[s]upersede

大於,

[mes]sage-supersede
1 个赞

大佬,fussy 用 flx-rs 这个后端时会丢候选,我已经在 fussy 报了 issue. 有空帮忙看看是什么问题。