TimothyQiu's Blog

keep it simple stupid

Vim 中使用 clang complete 为 C/C++ 自动补全

分类:技术

前文再续,书接上回。上回咱们讲到,如何在 Vim 中使用 OmniCppComplete 为 C/C++ 自动补全;今天偶然间发现了个新玩意儿:clang complete。

前情提要

OmniComplete 是 Vim 中的智能补全功能,而 OmniComplete 本身并不知道如何补全,具体的「通过光标前的内容猜测光标后可能出现的内容」的工作是由不同的外部插件实现的。

上回说到的 OmniCppComplete 就是这样一个插件。实际需要预先调用 ctags 对源代码进行词法分析(吧?)生成 tags 文件(token 列表),然后在这个 tags 文件中去进行匹配。所以局限也很快暴露出来:无论是库的头文件还是自己的源代码,都要用户自己事先对它运行一遍 ctags。

clang complete 则是借助 clang 来分析源代码,毕竟没有比编译器更了解代码的东西了。

如何安装

需要注意两个前提:

那么,你可以选择直接去 Vim 官方插件列表页获取,或者去作者的 GitHub clone,抑或使用 Vundle 安装即可。

如果获取的是 vmb 文件,那么命令行执行

vim clang_complete.vmb -c 'so %' -c 'q'

Windows 下则直接用 Vim 打开,然后 :source %……(呃,这好像也是废话 = =)

p.s. 强烈推荐试一试用 Vundle 来管理 Vim 的插件。

clang complete 是即拆即食的(OmniCppComplete 在安装完成后还需要到处生成 tag 文件),编辑状态输入 .->:: 后都会自动进行补全,一般状态下 Ctrl-X Ctrl-O 或者 Ctrl-X Ctrl-U 都能手动调用补全。

配置文件

如果在补全时发现提示「Pattern not found」提示,可以试试 :copen 查看错误信息。

错误信息很可能是语法错误,或者头文件未找到。

没错,因为 clang 是编译器,每次补全实际上都对整个源代码进行分析。要正确编译,可能需要额外传一些 -D 宏定义-I 头文件路径 给 clang。为了解决这一问题,clang complete 默认会在加载文件时读取该目录下名为 .clang_complete 的文件,该文件中就可以添加这样的信息,例如:

-DNDEBUG
-I../include
`pkg-config gtk+-2.0 --cflags`

当然,链接是不会执行的,所以不必把链接选项写进去。

其它

如果你觉得补全得慢,可以尝试让它使用 libclang 而不是 clang:

let g:clang_use_library=1
let g:clang_library_path="path to libclang"

这个功能需要你的 Vim 有 Python 支持……

Vim 中使用 OmniComplete 为 C/C++ 自动补全

分类:技术

OmniComplete 并不是插件的名字,而是 Vim 众多补全方式中的一种(全能补全)。说白了 OmniComplete 其实就是根据光标前的内容猜测光标后的内容,具体怎么猜取决于所采用的脚本。

而 OmniCppComplete 就是专为 C/C++ 编写的 OmniComplete 一个补全脚本。

那么经常和 OmniCppComplete 一起出没的 Ctags 又是什么呢?Ctags 全名 Exuberant Ctags,是一个独立的程序(也就是说,其实和 Vim 一点关系都没有)。它可以为各种语言的源代码生成语言元素(language object)索引文件。对于 C/C++ 来说,就是把源代码中的各种宏、函数、类、类成员等等元素和它们的相关信息生成索引文件,供其它程序使用。

OmniCppComplete 脚本就是根据 Ctags 生成的索引文件进行补全的。

好了,背景知识就是这样,安装步骤如下:

安装 Ctags

  1. 从官网下载 Ctags 可执行文件,网站是 http://ctags.sourceforge.net/
  2. 将下载到的文件(仅 EXE 文件即可)解压到一个目录,例如 D:/ctags
  3. 将该目录加入环境变量 PATH

准备索引文件

以生成 C++ 标准库索引文件为例:

  1. 下载专为 Ctags 修改过的 libstdc++ 头文件
  2. 将其解压到一个目录,例如 D:/ctags/cpp_src
  3. 使用命令行进入 D:/ctags/cpp_src 后执行:

    ctags -R --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ -f cpp .
    
  4. 建议将上一步生成的 D:/ctags/cpp_src/cpp 文件放到一个专门放置索引文件的目录以便后面的统一设置,例如放到 D:/ctags/tags

其它库的索引文件也可以依法炮制,只需切换到该库的 include 文件夹,执行:

ctags -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ -f <文件名> .

安装 OmniCppComplete

  1. 下载 OmniCppComplete
  2. 将下载到的文件解压到 ~/.vim (unix) 或者 %HOMEPATH%\vimfiles (Windows) 文件夹
  3. 在 vimrc 文件中加入
" ctags 索引文件 (根据已经生成的索引文件添加即可, 这里我额外添加了 hge 和 curl 的索引文件)
set tags+=D:/ctags/tags/cpp
set tags+=D:/ctags/tags/hge
set tags+=D:/ctags/tags/curl
" OmniCppComplete
let OmniCpp_NamespaceSearch = 1
let OmniCpp_GlobalScopeSearch = 1
let OmniCpp_ShowAccess = 1
let OmniCpp_ShowPrototypeInAbbr = 1 " 显示函数参数列表
let OmniCpp_MayCompleteDot = 1   " 输入 .  后自动补全
let OmniCpp_MayCompleteArrow = 1 " 输入 -> 后自动补全
let OmniCpp_MayCompleteScope = 1 " 输入 :: 后自动补全
let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]
" 自动关闭补全窗口
au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
set completeopt=menuone,menu,longest

另外,还需确认在 vimrc 中开启了 filetype 选项,不然 OmniComplete 无法自动识别 C/C++ 文件类型进行补全。

这样,在插入模式编辑 C/C++ 源文件时按下 .->::,或者手动按下 Ctrl+X Ctrl+O 后就会弹出自动补全窗口,此时可以用 Ctrl+N 和 Ctrl+P 上下移动光标进行选择。

美化咩?

也许你也已经注意到了一个问题,那就是「自动补全窗口的配色非常之丑」,Vim 自带的几个配色方案中只有两三种配色改掉了自动补全窗口丑陋的紫色,其它的基本上都是很逆天的用灰色表示当前选中项、紫色表示其他项。

要改变自动补全窗口的配色可以在 vimrc 中加上:

highlight Pmenu    guibg=darkgrey  guifg=black
highlight PmenuSel guibg=lightgrey guifg=black

Pmenu 是所有项的配色,PmenuSel 是选中项的配色,guibgguifg 分别对应背景色和前景色。