基于 Company 编写了一个带中文注释的英文补全助手

我配置了下面几个项,跟 company 体验就比较像了, 我还不习惯空格分词。

(use-package corfu
  :init
  (setq corfu-cycle t)
  (setq corfu-auto t)
  (setq corfu-quit-at-boundary t)
  (setq corfu-quit-no-match t)
  (setq corfu-preview-current nil)
  (corfu-global-mode))

我今天写了一个新的,主要的作用是把english-helper这类包里对company的依赖模拟了出来。解决了之前遗留的当前buffer没办法退出的问题。现在有几个优点:

  1. 通过模拟api的方式,使得依赖company的包可以在不修改源码的情况下直接运行在corfu上,包括可以使用模拟补全等功能,
  2. advice,可以完整支持 English-helper-company-togggle之类的包方法,而无需像之前那样单独写一个corfu-toggle。也就是说,之前激活和关闭使用toggle-company-english-helper, 现在也可以直接用这个命令切换,无需写额外的配置,支持了包自带的方法。
  3. 理论上其他依赖company的第三方包也能够直接使用,甚至无需什么额外配置。

使用方法,将下面的代码load进emacs。

  (defvaralias 'company-candidates 'corfu--candidates)
  (defalias 'company-mode 'corfu-mode) ;; should be deleted
  (defvaralias 'company-mode 'corfu-mode) ;; should be deleted
  (setq company-backends '())
  (setq completion-at-point-functions-backup completion-at-point-functions)
  (provide 'company)

  (defun set-completion-functions ()
    (setq completion-at-point-functions (cl-concatenate 'list (mapcar #'cape-company-to-capf company-backends) completion-at-point-functions-backup)))

  (defun company-grab-symbol ()
    "If point is at the end of a symbol, return it.
    Otherwise, if point is not inside a symbol, return an empty string."
    (if (looking-at "\\_>")
        (buffer-substring (point) (save-excursion (skip-syntax-backward "w_")
                                                  (point)))
      (unless (and (char-after) (memq (char-syntax (char-after)) '(?w ?_)))
        "")))
  (advice-add 'toggle-company-english-helper :after #'set-completion-functions)

关键是对需要使用的包的激活函数添加一句advice,用法就像上面的最后一行,比如我要使用一个名为“graphviz-company-mode‘ 的函数,那就写成:

(advice-add 'graphviz-company-mode :after #'set-completion-functions)

相当于骗了这些包:“我装了company,你随意运行吧”,其实只装了corfu哈哈哈

1 个赞

Untitled

这张图展示了几种状态:

  1. 没有启动English-helper,这个时候是corfu的补全
  2. 调用English-helper自带的toggle-company-english-helper,可以看到包激活了,并且在下方打印了enable
  3. 测试补全,能看到英文的中文提示了 4.继续调用 toggle-company-english-helper,功能被正确的关闭,打印了disable,然后补全恢复启用前的状态

我之前很少写elisp代码,这些都是东拼西凑的,也不知道对不对,大佬们如果愿意指点一下就太好了。我后面就更新在自己的配置文件里,尽量不让话题偏离english-helper了,会放到这个org文件的最后一个小节“simulate company with corfu”。使用corfu的感兴趣的童鞋可以参考一下啦

1 个赞

其实 company 挺好的,corfu 的优点好像是代码比较简单,貌似直接就是自带 capf 的一个 ui 一样的存在。

用 company 的话可以多个 capf 后端进行轮询,确定后是否直接通过 company-capf 使用,还是继续跟 company 自己的其他后端组合,可能性要更高一点,覆盖的使用领域也明显更广一点(至少对我来说是这样的,特别是现在很多应用接入 capf 后)。

2 个赞

我看corfu 的 wiki 中说,因为 Corfu 可以集成 Orderless ,对候选的过滤和选择是在 Emacs 即时完成的,不需要重新请求 LSP sever。这对于速度慢的 lsp server 来说,可能会快很多。

不知道各位用 Corfu 的有没有感觉快了 :smile:

原文:

速度没感觉,功能还少了不少

Orderless 我映像中 company 也可以用的吧?我早期切换过去又切换回来主要还是不习惯他的空格过滤搜索的设计,以及不支持分组。后面主要是有这样一个需求:

举个例子: 我有 citre, lsp 两个补全的后端,我可以把他们都加入到 completion-at-point-functions 中,citre 的优先级更高,capf 在这两个当中获取了数据之后。可以跟 company 的其他后端组合:

我还是来点代码说明吧:

(add-hook 'completion-at-point-functions #'lsp-completion-at-point nil t)
(add-hook 'completion-at-point-functions #'citre-completion-at-point -100 t)
;;; completion-at-point-functions 变量的值是这样的
(citre-completion-at-point lsp-completion-at-point t)
;;; 然后,我再来设置 company
(setq-local company-backends
              '((company-yasnippet company-capf
                                   company-dabbrev-code)
                company-files company-keywords
                company-dabbrev))

相当于有了一个两层结构,第一层是 capf 层面的,第二层是 company 层面的。

citre 那边有数据的话直接获取那边的数据,没有的话在获取 lsp 的数据,最终获取的结果就是 company-capf,而在 company 层面我可以对其进行组合或者其他操作,都是可以的,可能性多出许多。

1 个赞

在后端支持方面肯定是成熟的 Company 更加强大的。

我之前 company + orderless 的话,顺序会乱,所以就只在 vertico 中启用 orderless。这个情况我在 oderless 的 issue 列表中看到过好几次,不知道是否已经修复。

PS:如果用 consult 的话,有个包叫 consult-yasnippet,很好用,支持直接对搜索到的 snippet 在buffer 中进行实时预览。

1 个赞

功能是少了不少,Corfu 定位就是轻量化,组合更加灵活。需要的话,还可以适配 company 的后端。

lsp server 自己有增量的 cache。

1 个赞

在lsp server中过滤比在emacs中快吧,,什么lsp server能比emacs还慢,,,

不清楚,只是作者这么说,我具体没遇到过那么慢的 lsp。

其它的不是很清楚,比如 rust. lsp 补全的速度在我这里大概在 20-50ms,但是增量可以快到大概只需要 0.1ms。但这个增量是公共前缀的

请问下增量cache 是怎么打开的?我这 clangd 也差不多是20-50 ms

默认就是打开的,不需要设置。不过这个应该看 lsp server 的具体实现,也许有的是没有的。

1 个赞

使用 lsp-bridge 的时候都在玩 corfu , 最近基于 corfu 写了一个 corf-english-helper GitHub - manateelazycat/corfu-english-helper: English helper for Emacs, base on corfu-mode

感谢 @theFool32 大佬的帮助。

因为 corfu 是基于 child frame 的, 所以 corfu-english-helper 没有做对齐点处理,看起来更加清爽一些。

@Lewisliu 你可以换过来了。

2 个赞
(provide 'capf-english-helper)

应该是

(provide 'corfu-english-helper)

修复了,感谢提醒

capf 和 company 单词还没替换干净。