在 Emacs 下自动补全总是个问题,对于同一个 buffer 内的基于 symbol 补全 auto-complete-mode 做得非常好了,但是因为没有进行代码的分析,所以像结构体的成员变量或者类的成员函数的补全是不可能的。当然你可能试过这个号称最智能的GCCSence,但是我觉得这个东西够复杂的,在使用之前还需要用户手动运行一个命令来用 Gcc 处理一遍,它还会把一些东西放在 sqlite 数据库里面。这大概是因为 Gcc 不编译做静态分析工具造成的,在这里、这里、这里有讨论,Google 的一个静态分析的项目从 Gcc 迁移到 LLVM,重点是这:
The gcc version has been difficult to support and maintain, due mainly to the fact that the GIMPLE intermediate language was never designed for static analysis. The abstract syntax tree provided by Clang is an easier data structure to work with for front-end analyses of this kind.
这个 thread 挺好玩的,后面变成了一大群人争论 functional programming 和 Imperative Programming。这篇The Downfall of Imperative Programming再好好看看。
回到正题,我最近切换到 Mac 下。因为在 Mac OS X 下编译器变成了 Clang,Clang 是基于 LLVM 的。LLVM 对于分析代码是有比较方便的支持,所以基于 LLVM 有各种分析源程序的工具了,Xcode 下的一些辅助开发的工具还是很舒服的。前些天突然想到那么会不会有个东西来作为 Emacs 的自动补全的后端,一搜果然有了这个auto-complete-clang,使用了一下非常的方便。其实看看其代码是在后面调用 Clang 的,比如在 main.cc 源文件里面写一些代码:
#include <string>
#include <vector>
using namespace std;
class Demo{
public:
void print();
void test();
private:
int value;
};
int main() {
std::string s;
Demo demo;
demo.
}
结果还是非常精准的,不想截图了。后端运行的命令其实是:
cmd: clang -cc1 main.cc -fsyntax-only -code-completion-at main.cc:18:10
所得到的结果是:
COMPLETION: Demo : Demo::
COMPLETION: operator= : [#Demo &#]operator=(<#const Demo &#>)
COMPLETION: print : [#void#]print()
COMPLETION: test : [#void#]test()
COMPLETION: value : [#int#]value
COMPLETION: ~Demo : [#void#]~Demo()
auto-complete-clang 做的事情就是把这个结果再展示出来,其实这条命令也做了语法检查的,所以加上一个语法检查的功能应该也是可以的。一搜果然还是有了,看这个Realtime syntax checking with emacs,需要翻墙,不过代码在Github 上。其实其后端运行的命令是:
cmd: clang -fsyntax-only -fno-exceptions main.cc
最近用这个插件,基本代码都会是一遍编译通过啊,哈哈。Clang 错误提示也人性化一点,比如在 Xcode 下会提示你想的是不是”XXX”之类的。