打扰一下,关于用 cquery 时进行补全

看到有人推荐 cquery 我就试了一下, 编译成功了,也安装成功了(应该吧 )。

不过有个小问题,就是在进行补全的时候会这样 2018-02-26 14-29-02屏幕截图

我按下 tab 键之后就变成了下面这个样子 2018-02-26 14-29-18屏幕截图

我想问的是这里是不是什么地方设置出了问题,个人猜测他的原意应该是我按下 tab 或者其他什么按键之后光标在 $0, $1 上依次跳转?或者说有没有可能设置成这样子

emacs 版本:

cquery 相关设置:

(setq cquery-executable "/home/zmqc/backups/src/cquery/cquery/build/release/bin/cquery")

(add-hook 'c-mode-hook
	  '(lambda ()
	     (require 'cquery)
	     (lsp-cquery-enable)
	     (setq cquery-sem-highlight-method 'overlay)
	     (setq cquery-sem-highlight-method 'font-lock)))

(require 'lsp-imenu)
(add-hook 'lsp-after-open-hook 'lsp-enable-imenu)

多半和 cquery 无关,可能是 snippet 写的不规范,检查修改一下。

不然不太好解释 $1 $0 这俩东东。

看起来是 snippet-function 出了问题,但是我搜了一下 emacs-cquery 又没发现 snippet 相关代码,那么参数展开是怎么实现的?@MaskRay

还是说楼主举例的这个补全,根本不是 cquery 在起作用,而是纯粹的 snippet 模版?

像是company-yasnippey的效果

@ashfinal @twlz0ne

应该不是模板吧, 我看了下它对于自己定义的函数也是可以进行补全的,不过结果一样

相对的 yasnippet 却没有什么问题,比如 for 循环

2018-02-26 14-29-37屏幕截图

你安装了 company-lsp 吗?

因为 printf 是最基本的函数,我才会有疑问。

从后面的截图看,参数列表的 snippet 模版已经生成,但是在补全的时候没有执行(展开)

company-lsp 是通过 emacs 自带的包管理安装的

你可以尝试在 lsp-enable-cquery 之前 require company-lsp

好的,我试试看

你看看 company-lsp--snippet-functions 有什么

比如我这里是:

company-lsp--snippet-functions is a variable defined in ‘company-lsp.el’.
Its value is
(("java" . company-lsp--java-completion-snippet)
 ("python" . company-lsp--python-completion-snippet)
 ("rust" . company-lsp--rust-completion-snippet))

  This variable may be risky if used as a file-local variable.

Documentation:
Alist of functions to insert our snippets for each language.

[back]

可能是利用 GitHub - abo-abo/auto-yasnippet: quickly create disposable yasnippets 这个包来实现参数补全的?

可以检查下 auto-yasnippet 这个包安装了没。emacs 体系里我想不到还有其它简单方法实现参数补全的方案了。

company-lsp--snippet-functions is a variable defined in ‘company-lsp.el’.
Its value is
  
(("rust" . company-lsp--rust-completion-snippet))

This variable may be risky if used as a file-local variable.

Documentation:
Alist of functions to insert our snippets for each language.

emacs-cquery 没有hook completion

cquery以及其他基于libclang的工具补全的原理就像这个c-index-test命令

% c-index-test -code-completion-at=a.cc:5:8 a.cc -resource-dir ~/Dev/Util/cquery/build/debug/lib/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04/lib/clang/5.0.1
FunctionDecl:{ResultType int}{TypedText vprintf}{LeftParen (}{Placeholder const char *__restrict __format}{Comma , }{Placeholder __va_list_tag *__arg}{RightParen )} (50)
FunctionDecl:{ResultType int}{TypedText vscanf}{LeftParen (}{Placeholder const char *__restrict __format}{Comma , }{Placeholder __va_list_tag *__arg}{RightParen )} (50)
FunctionDecl:{ResultType int}{TypedText vsnprintf}{LeftParen (}{Placeholder char *__restrict __s}{Comma , }{Placeholder size_t __maxlen}{Comma , }{Placeholder const char *__restrict
__format}{Comma , }{Placeholder __va_list_tag *__arg}{RightParen )} (50)
FunctionDecl:{ResultType int}{TypedText vsprintf}{LeftParen (}{Placeholder char *__restrict __s}{Comma , }{Placeholder const char *__restrict __format}{Comma , }{Placeholder __va_list_tag *__arg}{RightParen )} (50)
FunctionDecl:{ResultType int}{TypedText vsscanf}{LeftParen (}{Placeholder const char *__restrict __s}{Comma , }{Placeholder const char *__restrict __format}{Comma , }{Placeholder __va_list_tag *__arg}{RightParen )} (50)

里面 CXCompletionChunk_Placeholder 会被替换成LSP的 ${1:foo} 这样的snippet,由company-lsp解释

ELISP> company-lsp--snippet-functions
(("rust" . company-lsp--rust-completion-snippet))

所以 cquery 不需要 snippet-function 了?

楼主可能没有配置 company-lsp?

(require 'company-lsp)
(push 'company-lsp company-backends)

我之前用 setq company-backends 加的 company-lsp, 现在换成你这种形式好像没有问题了。

非常感谢大家的帮忙

不懂 snippet-function 這些……

@zmqclee 另外可以試試 :detailedLabel t, Sarcasm加的

    (setq cquery-extra-init-params
          '(:cacheFormat "msgpack" :completion (:detailedLabel t) :xref (:container t)))

這裏 :xref (:container t)是期待有一天有人把引用的lexical container在客戶端顯示出來

嗯,好的,非常感谢。。。

就是用来把参数列表转换成 snippet 的函数,company-lsp 自带了一个例子:company-lsp–rust-completion-snippe

既然 cquery 输出的参数列表已经是 snippet,就不需要实现这个函数了。

其实很多语言的 company backend 都不需要这个 snippet-function,因为 company-mode 有另外一种实现 company-template-c-like-templatify

具体到某个语言比如 company-go 是这样的(不依赖 snippet):

(defun company-go--insert-arguments (meta)
  "Insert arguments when META is a function or a method."
  (when (string-match "^func\\s *[^(]+\\(.*\\)" meta)
    (let ((args (company-go--extract-arguments (match-string 1 meta))))
      (insert args)
      (company-template-c-like-templatify args))))

可以运行这句看看效果:

(company-go--insert-arguments
 "func Errorf(format string, a ...interface{}) error")

company-go--insert-arguments

所以这个 snippet-function 的使用场合是:当你使用了 lsp-FOO 并且刚好没有配套的 company-FOO,这时候就需要写一个 company-lsp--FOO-completion-snippe 来处理参数列表。

2 个赞

大概明白snippet是什么了。

DaanDeMeyer给cquery加了cmake https://github.com/cquery-project/cquery/pull/526

有望取代waf

改进了#include补全。company-lsp可以用

#i" 补全 #include "user_header"

#< 补全#include <system_header>

补全都用上了从clangd抄+改的fuzzy_match.cc

遇到同样的问题了,使用本题解决方案还是没有解决。依然是snippet没有生效。