补全选项顺序,字典排序还是长度排序,哪个更好点?

Racket Mode 产生的补全顺序是字典排序:

(sort (map symbol->string (namespace-mapped-symbols))
      string<?)

比如匹配前缀 regexp-match 有如下结果,但是我想要的 regexp-match? 仅仅少了一个字母,却被排到了最后一个,用 Company 的话还要翻页,这正是字典排序的结果,是不是按长度排序要好些(长度相同在用字典排序)?还是有更智能的方法。

regexp-match
regexp-match*
regexp-match-evt
regexp-match-exact?
regexp-match-peek
...
regexp-match/end
regexp-match?
1 个赞

是的,感觉长度优先要更合理一些。

不应该最好和 helm 那样做成输入 r m ? 分别匹配每个词元第一个字母的模糊匹配么?

precient好像是长度排序

一直没搞明白 Emacs 补全是如何工作的,就算我把 Racket Mode 生成的补全按长度排序,Emacs 依旧按字典排序,自带的 M-x complete-symbol 和 Company Mode 都是。Emacs 还有个 completion-styles 选项,我没有调整,我也不明白是干嘛的。

这个,开箱即用,挺好的

我也推荐这个,虽然 fuz 很好,安装确实麻烦些。而且 prescient 居然性能很不错。

这个人还写了ya ivy/helm替代,说是ivy写得太乱,要搞个更简洁的。不知道有人试用过没

我连 Emacs 自带的补全机制怎么用还没搞明白,(elisp) Programmed Completion 看不懂,Emacs 自带补全跟 Minibuffer 搅合在一起,Minibuffer 应该只是一个前端(UI 交互),Helm 使用 Buffer,Ivy 使用 Minibuffer、Company 使用 Overlay,自带补全机制应该更抽象一些,文档应该介绍补全是如何工作的,API 怎么用,并且给出例子。

这个是 sly 在 Common Lisp 侧实现的模糊匹配。右边的百分比是匹配率。应該论外。

然而下面是 geiser-chez + company 的

和 ielm 的一样

snails欢迎你

高级,还有百分比显示

试过了,还很初级,功能没得比。

string<? 函数在哪个包?

string< 排序结果是 regexp-match? 项始终排末尾:

#+BEGIN_SRC emacs-lisp :results value list
(sort '("regexp-match-exact?"
        "regexp-match-peek"
        "regexp-match-evt"
        "regexp-match/end"
        "regexp-match?"
        "regexp-match*")
      'string<)
#+END_SRC

#+RESULTS:
- regexp-match*
- regexp-match-evt
- regexp-match-exact?
- regexp-match-peek
- regexp-match/end
- regexp-match?

string< 比的是大小,而不是长短。


找到原因了,是 completion-at-point 中调用了 completion-in-region 又重新排了序:

(completion-in-region (point) (point)
                      '("regexp-match*"
                        "regexp-match?"
                        "regexp-match-evt"
                        "regexp-match-exact?"
                        "regexp-match-peek"
                        "regexp-match/end"))
;; =>
;; "regexp-match*"
;; "regexp-match-evt"
;; "regexp-match-exact?"
;; "regexp-match-peek"
;; "regexp-match/end"
;; "regexp-match?"
1 个赞

这个是 Racket 的。

从函数名看,作用应该跟 string< 一样。

结合我前面的回帖,补全项的排序有两个点需要注意:

1. 排序函数

对于存在链接符的字符串,string< 的结果不符合预期:

#+BEGIN_SRC emacs-lisp :results value list
(sort '("foo*" "foo-bar" "foo?")
      'string<)
#+END_SRC

#+RESULTS:
- foo*
- foo-bar
- foo?
#+BEGIN_SRC emacs-lisp :results value list
(sort '("foo*" "foobar" "foo?")
      'string<)
#+END_SRC

#+RESULTS:
- foo*
- foo?
- foobar

2. completion-at-point 内部的二次排序:

completion-at-point
-> completion-in-region
--> completion--in-region
---> completion--in-region-1
----> completion--do-completion
-----> minibuffer-completion-help
(setq completions
      ;; FIXME: This function is for the output of all-completions,
      ;; not completion-all-completions.  Often it's the same, but
      ;; not always.
      (let ((sort-fun (completion-metadata-get
                       all-md 'display-sort-function)))
        (if sort-fun
            (funcall sort-fun completions)
          (sort completions 'string-lessp))))

除非指定了 sort-fun,否则默认使用 string-lessp(即string<),也就会出现第 1 点所说的问题。

4 个赞