去年正经入了emacs的坑, 使用doom用到现在, 不断的体验到流水般的顺畅.
有一个问题一直困扰我. 如图, 在默认的config.el中, 也就是elisp模式中, 我录入三个字符后, 然后control-n, company会给出弹窗补全.
但是在python-mode中, 我录入三个字符, control-n, company直接输入了一个词, 没有弹窗. 即使前缀匹配了好几个keywords.
我看到两个mode下的backends都是一样的.
新用户只能发一张图, 所以截屏拼了一下. 上面是company_backends配置. 下左是python中无法弹窗补全的状态, 下右是elist中正常补全弹窗的状态.
为什么在elisp下输入quick会出现弹窗, 而python中输入rec则不会.
能不能让company无论如何都弹窗揭示候选词.
我的doom配置打开了:complete中的company.
这个问题导致在最常用的buffer内关键词补全的时候, 经常control-n超过了正确的词, 从而要删几个字符才能补全正确. 很影响效率.
没用 Doom。是不是由于两个 mode 之中 C-n 补全的函数不一样?你分别在两个 mode 中 M-x describe-key
然后按 C-n 看看?
company-backed 中的company-capf
使用的是 completion-at-point-functions
这个变量来控制具体的自动补全来源的。
elisp中和python中这个 completion-at-point-functions
(也叫做capf) 的值是有差别的。
根本问题就是 你的 python中的这个capf 函数可能跟你想的不一样,或者你没有配置对。
具体要看python补全中capf函数具体是哪个。
1 个赞
两个c-n都指向evil-complete-next
感谢 guanghui.qu的提醒.
看了一下, 在python-mode中, capf的值为
(python-completion-at-point
t)
而elisp-mode中, capf值为
(elisp-completion-at-point
tags-completion-at-point-function)
差异应该就来自于此.
不过我最后没有使用这个解决, 因为我发现我期望的是buffer内的关键词补全, doom的默认值给得不太对.
我最后添加了两个修改, 在
此修改完成后需要运行doom sync才会生效.
同时在config.el中加入了一行.
(modify-syntax-entry ?_ “w”)
前一个修改是为了把添加dabbrev和files这两个后端.
后一个修改是为了告诉emacs把下划线视为词的一部分.
通过这两个处理之后, 目前已经达到了目的.
感谢热心回复的小伙伴们.
1 个赞
直接在 config.el
里面修改 +lsp-company-backends
就可以吧
因为我是从vim迁移过来的, python的代码补全和vim一样共用了youcompleteme, 为了图省事就没有再配置lsp.
以后可能会试试lsp, 大家都说好, 我曾经尝试了几次但是没有迁过去.
1 个赞
有个诊断命令 M-x company-diag ,可以看到当前正在用的哪个后端,会有一定帮助。
1 个赞
似乎还是有些问题, 在org-mode中还是不弹窗, 直接补全, 今天新的进展是发现这个行为似乎不是backends的问题, 而是frontends.
company-frontends,好像是可以对选项进行过滤, 弹窗应该的应该是company-box这个frontend, 而不弹窗的是(company-pseudo-tooltip-unless-just-one-frontend) 这个frontend.
此时手工设置company-box-mode无效.
而且在org-mode直接补全时会有行提示:
Expansion found in ‘ *org-src-fontification:sh-mode*,
company-pseudo-tooltip-unless-just-one-frontend
这个前端意思就是只有一个候选项就不弹窗
1 个赞
最终解决了. 目前在org-mode和python中, 都如预期达到了目的.
之前帖子中对于autoload的修改不太对, 将capf设置为首选补全应该是有道理的. 根本的问题在于frontends. 刚开始的时候frontend在两个mode中应该是不同的. 特别是 xhcoding提到的just-one-frontend, 可能还有默认的preview-frontend.
最终的话, 在init.el中. 开启
(company +childframe) ; the ultimate code completion backend
选项, 使用company-box-frontend, 然后在config.el中设置.
(add-hook 'company-mode-hook 'company-box-mode)
(setq company-frontends '(company-box-frontend))
解决了此问题. 再次感谢朋友的热心回复.
1 个赞
进一步的总结. doom-emacs中使用evil, everywhery.之后默认insert时的C-n绑定到evil-complete-next下.
evil-complete-next调用的是evil的补全, 这时是没有弹窗的, 弹窗是company的功能, 弹窗通过minimum-prefix这个变量的最小前缀来触发.
这里容易混淆的就是doom-emacs中在evil-insert-state-map下和弹窗后的company-active-map两个模式下的补全快捷键都是C-n, 所以就容易搞错.
(define-key evil-insert-state-map (kbd "C-n") #'company-complete)
(with-eval-after-load 'company
(define-key company-active-map (kbd "C-y") #'company-complete-selection)
(define-key company-active-map (kbd "C-p") #'company-select-previous-or-abort)
(define-key company-active-map (kbd "C-n") #'company-select-next-or-abort)
(setq company-selection-wrap-around t)
(setq company-minimum-prefix-length 3))
这样evil插入时的补全替换为company-complete唤出弹窗, 然后使用c-n c-p循环. 如果只有一条备选就直接插入. 否则在整个环境中循环.
一些补充的后续. 如果有搜到的朋友, 可能有些助益.