elpy有一个补全比较好的地方就是,在jedi没有返回结果的时候,会去获取dabbrev的结果:elpy-company-backend
(cond
;; The backend returned something
(result
(elpy-company--cache-completions arg result))
;; Nothing from the backend, try dabbrev-code.
((> (length arg) company-minimum-prefix-length)
(elpy--sort-and-strip-duplicates
(company-dabbrev-code 'candidates arg)))
;; Well, ok, let's go meh.
(t
nil))
我把backend设成(company-lsp company-dabbrev-code)
这样子是没办法自动触发company-dabbrev-code
的。
把backend设成((company-lsp company-dabbrev-code))
或((company-lsp :with company-dabbrev-code))
这样,补全的时候有轻微卡顿,并且结果也没有合并,重复选项非常多,排序也怪怪的。
我期待的是和elpy一样的结果,就是当lsp完全没有结果返回时才使用company-dabbrev-code
。但是(company-lsp company-dabbrev-code)
这样为什么不会自动触发company-dabbrev-code
?输入一个lsp不会有结果的词,company-diag
也显示的是Used backend: company-lsp
。对这个词手动company-dabbrev-code
是有结果的。
是否必须通过像(company-dabbrev-code 'candidates arg)
这样注入代码到company-lsp
才能达到效果?
yicao
2019 年1 月 26 日 04:12
2
我用ccls也遇到了这个问题,我自己的方案是,默认使用company-dabbrev-code,这样速度比较快,company-lsp绑定了一个快捷键 (Ctrl+Tab) ,在需要的时候手动触发,目前使用没啥障碍,速度也没什么影响
多个backend和group的backends从来就没搞彻底懂过。。company-backends
下面那一大段文档读了,实际多个backends使用时触发还是像谜的一样,难怪issue里那么多人也不懂backends的相互关系。。
我是想把它搞得稍微智能一点点。。因为不太喜欢手动触发。。哪怕需要配置。。曾经用过一位大神的hippie expand的配置,效果非常好,但是因为要手动触发,渐渐就不用了。。隔壁贴说模糊匹配之类的,我已经不敢指望了。。
'(A B)
这样的时候不重复还是可以做到的吧,是不是因为lsp有自动snippet之类的所以没有把相同的项识别出来?那大概需要自己手动把两个backend合并一下,感觉很难……
对于lsp与dabbrev这种主力的backend,我是比较倾向于当一个backend完全没有结果的时候才使用下一个。不然的话排序也是个问题。所以elpy也是直接在callback里做(使用另一个backend)这件事。
我有个地方不太明白,输入一个不存在的prefix,例如:“haha”,company-lsp
里返回的prefix是"haha",但此时其实它不能补全,为什么没办法把控制交给下一个backend?是因为它是个async的backend的缘故?company-backends
的文档里说要返回nil
才把控制交给下一个backend。
我看了一些别的一些backend也会有这样的,这样的意思是不是要求每一个company-backends
里面的元素都是一“类”backend?因为不同“类”才会使触发prefix不一样(比如company-files
不在字符串里会自动不补全)。否则,prefix不是nil
,但又不能补全,company-backends
里塞一大堆那有什么用。。
文档里说Only one backend is used at a time。好奇为什么没法做到一个backend没结果了,就按顺序触发下一个,哪怕此时prefix不是nil
?
如果一个后端没有补全结果,compnay就会按顺序启用下一个。这个跟prefix返回的结果没关系。
似乎并不会。例如在一个elisp buffer里如果company-backends
的值为(company-elisp company-dabbrev-code)
,文件内容为:
(defun hahahaha ()
)
haha*
此时光标在*处的话,是不会触发company-dabbrev-code
的。因为文档里说当一个backend调用prefix时返回nil,才会触发下一个。但此时company-elisp
返回的prefix是haha
,所以不会触发下一个。
也就是说“应不应该补全”和“能不能补全”不太一样。但“不能补全”时如果prefix不是nil
的话,应该是不会触发下一个的。
Returning nil from this command passes
control to the next backend. The function should return stop if it
should complete but cannot (e.g. when in the middle of a symbol).
之前遇到同样问题, 并提了一个issue: For a backend group, if the first backend gives candinates, how to discard candinates from the second backend? · Issue #806 · company-mode/company-mode · GitHub
我的想法跟LZ稍微不同, 我是想让两个后端同时开工, 这样(理论上)响应速度快, 如果第一个backend有返回结果, 就把第二个的丢弃, 用第一个, 如果第一个没有返回结果, 就用第二个的.
company目前不支持这样, 不过issue里面最后提供的方法也很接近想要的效果, 可以试试.
lsp补全的工作大部分在外部的lsp服务器, 所以可以并行. company目前就相当于并行的, 因为backend很多都是异步, 只需要提供上面提到的丢弃的功能即可.
:separate
那种方法,结果不会合并。。好多重复
你可以看下那个issue的跟帖, 里面就是在讨论这个问题, 最后有一个方法还可以
里面本来也没说会合并啊, 最后的效果是让补全项按backend的顺序显示, 比如company-lsp的补全项显示在前面, 另外一个的显示在后面, 这样保证了你优先看到company-lsp的补全项
这个问题有办法了吗,company-lsp为什么会在没结果的时候阻止后面的backends触发啊?
这个问题的影响不算非常大,因为company-lsp会给出当前scope可用的变量、函数等符号,基本算是包括了company-dabbrev-code的功能,只剩关键字之类的没法补全。
SGNH
2019 年10 月 20 日 04:12
18
可以在补全结果增加一个后端标识符,选候选时可以输入后端标识符列出该后端的匹配项,参考vscode不知道行不行