2017-07-13-emacs配置ycmd补全
Table of Contents
1 ycmd介绍
它本来是vim上的插件 YouCompleteMe
。现在整成了一个通用的。
可以补全很多语言: C,C++,C#,python,js,go
等。看看下面就知道它支持
多少语言了。
C-family, C#, Go, JavaScript, Python, Rust, and TypeScript languages are supported natively by YouCompleteMe using the Clang, OmniSharp, Gocode/Godef, Tern, Jedi, racer, and TSServer engines, respectively.
language | backend |
---|---|
C-family | Clang |
C# | OmniSharp |
Go | Gocode/Godef |
JavaScript | Tern |
Python | Jedi |
Rust | racer |
TypeScript | TSServer |
它可以是基于语义的和不基于语言的。根据不同的语言,把两种的结果都汇 总后一起返回。
ycmd
是 client-server
架构的。我们使用的编辑器 vim, emacs
等等
都是client。真正的server是在它们需要补全的时候启动。server的工作是解
析源码文件,给client返回需要补全的内容。
server端能补全这么多类型的代码,光使用ycmd是搞不定的。 比如对于
C-family
的语言,ycmd补全功能需要 libclang
,它是编译器clang的
libary,一般也叫llvm。ycmd会用它来分析源文件。
ycmd使用不同的编译参数才能支持不同的语言, ./build.py --all
是支持
ycmd可以全部补全的语言。不过不推荐使用它。依赖太多啦。编译方面具体可
以参考 编译ycmd 。
2 编译ycmd
2.1 基本步骤
Dependencies
- 编译需要使用 python3 环境。建议使用virtualenv来新建一个 python3 的环境。可以参考 python使用virtualenv 。
- 支持
c-family
语言需要使用libclang
。编译时会自动下载,如果 自动下载很慢,可以参考 编译时下载libclang很慢。
从源码编译ycmd需要下面几步:
clone源码:
git clone https://github.com/Valloric/ycmd.git
更新子库
git submodule update --init --recursive
根据官网上说的直接调用下面这句编译可能会因为依赖太多,不一定编译 得过:
./build.py --all
使用 ./build.py --help
查看一下:
(python3) ~/github/ycmd/ [master] ./build.py --help usage: build.py [-h] [--clang-completer] [--system-libclang] [--omnisharp-completer] [--gocode-completer] [--racer-completer] [--system-boost] [--msvc {12,14,15}] [--tern-completer] [--all] [--enable-coverage] [--enable-debug] [--build-dir BUILD_DIR] optional arguments: -h, --help show this help message and exit --clang-completer Build C-family semantic completion engine. --system-libclang Use system libclang instead of downloading one from llvm.org. NOT RECOMMENDED OR SUPPORTED! --omnisharp-completer Build C# semantic completion engine. --gocode-completer Build Go semantic completion engine. --racer-completer Build rust semantic completion engine. --system-boost Use the system boost instead of bundled one. NOT RECOMMENDED OR SUPPORTED! --msvc {12,14,15} Choose the Microsoft Visual Studio version (default: 15). --tern-completer Enable tern javascript completer --all Enable all supported completers --enable-coverage For developers: Enable gcov coverage for the c++ module --enable-debug For developers: build ycm_core library with debug symbols --build-dir BUILD_DIR For developers: perform the build in the specified directory, and do not delete the build output. This is useful for incremental builds, and required for coverage data
--clang-completer
可以编译c-family
语言的补全。它会下载它需 要的libclang到clang_archives
目录。如果你觉得下载速度太慢,也 可自己下载放进去--omnisharp-completer
对C#
--gocode-completer
对go
--tern-completer
对js
- …
这样看来,如果需要对 c-family
系语言进行补全,直接使用
./build.py --clang-completer
就可以了。
注意 :我当前在 ebf04bafde342f2be5fd5717f368ebbe8bf6643c
这个
commit-id上编译的,此时需要使用 4.0.1
的libclang版本。我发现编译
ycmd的时候,需要使用 python3 才行。使用 python2 可能编译能成功,
但是编出来不有正常使用。
编译完成后,最好是测试下能不能使用,可以参考 测试ycmd是否能正常工作 。
2.2 编译时下载libclang很慢
下载clang编译器真的时太慢啦。可以到其它网络好的机器上先下载下来。我
是去云主机上使用wget下载的。当然,需要找到当前下载的clang的版本。这
个在 ./build.py --clang-completer
执行时会有输出。
wget http://releases.llvm.org/4.0.1/clang+llvm-4.0.1-x86_64-apple-darwin.tar.xz
下载好后,直接放到ycmd的 clang_archives
目录下。然后直接
./build.py --clang-completer
就可以编出来对 c-family
语言的补全。
2.3 编译ycmd时可能出错
如果第二次编译,可能失败,出现错误:
Error: could not load cache
这种情况下,需要把 cpp
目录中的 CMakeCache.txt
文件删掉。这时再
重试就可以了。
3 测试ycmd是否能正常工作
从ycmd目录进入 examples
目录可以直接运行测试。
cd examples/
pip install -r requirements.txt
./example_client.py
测试脚本一定要运行在 python3 。所以改一下:
mkdir -p /tmp/python3/
virtualenv -p /usr/local/bin/python3 /tmp/python3/
cd examples/
pip install -r requirements.txt
./example_client.py
这个测试是对全部ycmd支持的语言。所以如果没有编译对js的支持,它会报错 的。不用care,只要你需要的补全是ok的就好。
4 emacs-ycmd
在emacs中使用,可以直接使用 emacs-ycmd
这个插件。
(require 'ycmd) ;;; 这个设置编译出来的ycmd目录。注意这里的ycmd不是一个可执行文件,而是 ;;; 一个目录,注意需要使用python3 (set-variable 'ycmd-server-command '("/usr/local/bin/python3" "/Users/pengpengxp/github/ycmd/ycmd")) (set-variable 'ycmd-global-config "/Users/pengpengxp/src/asp/nginx/.ycm_extra_conf.py") ;;; 设置等待server的时间,默认是3s (setq ycmd-startup-timeout 5) ;;; 当ycmd-mode开启后,把ycmd加入到默认emacs的补全中,这样可以使用 C-M-i 来补全 (defun ycmd-setup-completion-at-point-function () "Setup `completion-at-point-functions' for `ycmd-mode'." (add-hook 'completion-at-point-functions #'ycmd-complete-at-point nil :local)) (add-hook 'ycmd-mode #'ycmd-setup-completion-at-point-function) ;;; show debug info to *Messages* buffer (setq url-show-status t) ;;; tab setup (setq tab-always-indent 'complete) (defun peng-setup-ycmd () " setup ycmd, add `ycmd-complete-at-point' to `completion-at-point-functions' so that `C-M-i' can toggle the complete. " (interactive) (ycmd-mode 1) (add-hook 'completion-at-point-functions #'ycmd-complete-at-point nil :local)) (provide 'init-ycmd)
这样配置好后,使用 C-M-i
就可以调出补全内容啦。
5 C-family language
使用libclang的时候,它需要知道编译时提供的编译参数。这样libclang才能
分析代码,ycmd才能提供 c-family
基于语言的补全。有两种方式可以得到
编译选项。
5.1 emacs配置
把下面的函数和 emacs-ycmd 中的 peng-setup-ycmd
函数加入到
cc-mode
的hook中就可以了。
(defun peng-setup-cc-mode-for-complete () "use tab to indent and complete. tab on left will act as indent while on the right of character as `completion-at-point' " (interactive) (setq c-tab-always-indent 'nil) (setq c-insert-tab-function #'completion-at-point) )
有时候找不到对应的补全时,可以使用
ycmd-toggle-force-semantic-completion
把基于语言的补全强制打开。这
样它会去分析文件啦。
5.2 手动提供编译选项
对于编译选项,可以使用 .ycm_extra_conf.py
文件机制来靠诉ycmd我的
编译选项。比如我写测试readline的函数。当前目录结构是这样的:
/tmp/readline/ ├── hello.c ├── main.c ├── makefile └── test.cpp 0 directories, 4 files
要对这个preject进行补全,新建一个 .ycm_extra_conf.py
文件,它就包
括一个函数就可以啦:
def FlagsForFile( filename, **kwargs ): return { 'flags': [ '-x', 'c', '-Wall', '-Wextra', '-Werror', '-lreadline' ], }
需要关注的只是 flags
这一行。把所有需要的flag就这样一个一个写进去
就可以啦。前面的两个选项 -x
和 c
是选择C语言,cpp就把 c
换成
cpp
就可以啦。
对于一些大型的项目,手动编写 .ycm_extra_conf.py
太麻烦,可以考虑
下使用 ycm-generator 。它的基本用法:
./config_gen.py -x c++ ~/src/ASP-Engine/core/src