您的位置:首页 > 编程语言 > Python开发

vim中的杀手级插件: YouCompleteMe

2014-03-07 18:09 696 查看
转自:http://zuyunfei.com/2013/05/16/killer-plugin-of-vim-youcompleteme/

vim中的杀手级插件: YouCompleteMe

Vim代码补全现状

在漫长的Vim发展历史中,代码补全一直是比较被忽视的环节,相比众多IDE,vim本身的代码提示功能包括其众多补全插件显得无比简陋, 这是因为vim的先天不足,它是文本编译器,不能理解程序语意。引用王垠的一段文字:
“文本编辑器”这种东西一般都不真正的理解程序语言。很多 Emacs 和 vi 的用户以为用 etags 和 ctags 这样的工具就能让他们“跳转到定义”,然而这些 tags 工具其实只是对程序的“文本”做一些愚蠢的正则表达式匹配。它们根本没有对程序进行 parse,所以其实只是在进行一些“瞎猜”。简单的函数定义它们也许能猜对位置,但是对于有重名的定义,或者局部变量的时候,它们就力不从心了。
《编辑器与IDE》www.yinwang.org/blog-cn/2013/04/…或许对于python,PHP等动态语言,因为本身的语言特性和丰富的工具支持,也能做到不错的补全效果,但对于C/C++代码的补全, AutoComplPop, omnicppcomplete, neocomplcache等插件的确都是在“瞎猜”。

还有一个原因是没有大牛来做这些功能。在漫长的Vim或emacs历史中,它都是掌握在少数精英程序员手里,扩展它都需要一定的专业知识,我辈普通程序员只是在使用它。而代码补全并不是大牛们的必须,我曾经和一个瑞典的PSE做Pair Programming, 只使用emacs和grep等linux命令,他就可以在整个工程里穿梭自如,常用库的调用了然于心,代码结构清晰,几乎没有语法和拼写错误。估计他看到我花里胡哨的vim, 还用代码提示,心里也是一阵鄙视吧。所以尽管大牛们让emacs可以煮咖啡,vim可以发微博,但是vim和emacs的代码提示一如既往的烂了二三十年。
在Apply公司支持的LLVM/clang诞生后,事情迎来了转机。clang强大语义分析能力,为C/C++/Object-C源代码级别的分析和转化提供了可能,基于clang的语意补全插件开始在vim和emacs上出现。

YouCompleteMe

YouCompleteMe是一个比较新Vim代码补全插件,可以基于clang为C/C++代码提供代码提示。它安装配置简单,Bug 很少。 对C/C++来说youcompleteme现在应该是最好选择,借助clang的强大功能,补全效率和准确性极高,而且可以模糊匹配(见下面的demo)。不管你的C++代码用什么怪异的写法,只要能编译通过,都能补全,即使是C++11的lambda和auto都没有障碍,比codeblock这些根据tag index补全的IDE都要强大。


YCM的安装配置

YCM需要最新版本Vim(7.3.584)的支持,从代码编译Vim的方法看这里
使用Vundle安装 youcompleteme后,需要先编译才能使用。
1
2
cd ~/.vim/bundle/YouCompleteMe
./install.sh --clang-completer
语意补全要正确工作,需要配置好.ycm_extra_conf.py文件,模板在这里。可以把这个文件放在项目的根目录下,打开项目文件时,YCM会循环向上搜索并加载这个文件,或者在vimrc文件中加入
1
let g:ycm_global_ycm_extra_conf = 'your path to .ycm_extra_conf.py'
如果.ycm_extra_conf.py中include path等配置没有问题,YCM已经可以工作了。
YCM更新很频繁,最近版本已经可以和UltiSnip整合了。

2013-08-14更新

集成Syntastic

YCM很早就支持集成Syntastic了,上面demo里面,代码前的出现红色叉叉,就是YCM结合Syntastic爆出的语法错误。刚开始用YCM的时候,更看重其代码补全功能,Syntastic没放在心上,结果发现越用越离不开了。当编写C++代码的时候,每次光标悬停2秒钟以上的时候,YCM都会在后台扫描你当前的文件,你刚刚输入的代码有什么编译错误,马上就能显示出来,及时的改掉,不再积累到最后编译的时候。当然这是现代IDE的标配功能,vim中也有插件可以实现,但是有了YCM后,再用vundle安装Syntastic,甚至不用任何配置就实现了这些功能,实在是太方便了。


代码跳转

YCM支持代码跳转了,又一项对程序开发极有用的功能,现在支持c, cpp, object-c, object-cpp, python代码跳转到声明和实现。特别对c和c++, 这个跳转可不是像基于ctags的那些插件,经常让你在一大堆重名的tag里人肉搜索,十跳九不中。得利于clang的强大功能,YCM的代码跳转几乎没有失手,当然前提是你要设置好
.ycm_extra_conf.py
,代码被YCM解析时没太多编译错误。
主要功能是3个YcmCompleter的subcommands:
GoToDeclaration

GoToDefinition

GoToDefinitionElseDeclaration

在vim配置文件中加上一行就搞定了
1
nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR>
VimVim, Vim plugin

Comments

多说Disqus最新最早最热44条评论

8条新浪微博

1条腾讯微博



小熊可惜在win下不能工作
2013年6月30日回复顶转发

cloudzuwindows下没有试过,你可以参考下: https://github.com/Valloric/YouCompleteMe/wiki/Windows-Installation-Guide
2013年7月1日回复顶转发


ccWin下编译通过了,现在还没有弄明白怎么配配置文件
2013年8月6日回复顶转发

cloudzu主要是要设置好头文件的搜索路径,你可以参考下我的配置文件
https://github.com/yunfeizu/dotfiles/blob/master/vim/toolkit/ycm/ycm_extra_conf.py
2013年8月8日回复顶转发

cc晓得了,lz有试过在c++文件中补全c头文件里的函数没。目前,我这里能补全c++头文件里的了,但是不能补全c头文件里的函数。是不是我少配置了什么?
2013年8月12日回复顶转发

cloudzu很少需要用到补全C函数,貌似和clang的参数有关,不过编译器的配置不是常人能懂的。最快的方法,问ycm的作者

,去github上提个issue吧:https://github.com/Valloric/YouCompleteMe/issues?page=1&state=open, Valloric回复的相当快。
2013年8月14日回复顶转发

cc昨天浏览了下YCM的issue,找到解决方法了。Valloric说c函数不会自动补全,需要手动执行补全命令。默认的快捷键是<C-Space>,中文用户可能需要绑定下快捷键。写在这里,好让其他朋友看到~
2013年8月15日回复顶转发


azure回复 cc: clang对win的支持不行,如果用了vc的一些语言特性,比如特定的warning之类的,完全搞不定
2013年8月20日回复顶转发


housansan回复 cc: 补全printf没有??是不是.ycm_extra_conf.py要修改什么?
2013年12月14日回复顶转发


cc回复 housansan: YCM默认不自动不全C的全局函数(比如printf,scanf),如果需要补全需要手动执行。YCM默认的手动补全的快捷键是<C-Space>,对应的命令是ycm_key_invoke_completion,而<C-Space>在中文环境下默认是切换输入法的快捷键,所以要重新绑定快捷键。不是在.ycm_extra_conf.py做修改,而是在.vimrc里做修改,比如重新绑定为<S-Space>即Shift+空格可以了。
2013年12月15日回复顶转发


cloudzu回复 cc:

解释的很清楚
2013年12月16日回复顶转发


housansan回复 cc: 有什么方法能自动补全全局C,像C++一样补全函数,找了半天没找到
1月11日回复顶转发


hominlinx你好,请问在vim中如何比较好的实现,我输入{}时,代码能够想ST2一样将}回车,并光标移动到{的下一行?谢谢诶
2013年9月1日回复顶转发

cloudzu没有用过类似的功能,我有在用autopair,输入{, 会自动补全}, 这时候光标是在两个括号中间的。然后打回车,在开启了autoindent 和smartindent的vim中, vim会把} 移到第三行,光标移到第二行,并做好缩进。如果有什么更好的办法,还望告知。
2013年9月2日回复顶转发

hominlinx你好,我用了delimitMate 自动补全,这个也可以将光标移到括号中间,根据你的方法,我在.vimrc中设置了set smartindent 和set autoindent ,但是我单击回车时,此时}会在第二行,光标在}上面,为何啊?
2013年9月2日回复顶转发

cloudzu我又仔细看了一下,回车的时候插入一行应该是autopair的功能,不知道delimitMate是否有类似的功能。
autopair的文档有如下描述:
g:AutoPairsMapCR

Default : 1Map <CR> to insert a new indented line if cursor in (|), {|} [|], '|', "|"
execute 'inoremap <buffer> <silent> <CR> <C-R>=AutoPairsReturn()<CR>'
2013年9月2日回复顶转发



Tao Honker你好,好像c-support (c.vim) 这个插件有类似的功能:输入 `{`,赶快敲回车,光标就在下一行缩进位上,且在下下行有一个 `}` 补全。
2013年12月21日回复顶转发


hominlinx你好,我在使用GoToDefinition时候经常出现:Can't jump to definition. 这是为啥啊?
2013年9月1日回复顶转发

cloudzu如果不是源文件有太多编译错误,可能是程序结构的问题,并不是所有的函数都可以找到定义,特别是一些库函数,一般最好用GoToDefinitionElseDeclaration,大部分时候跳到声明就足够了
2013年9月2日回复顶转发


hominlinx你好 在使用YCM时,对于大型的工程,工程里面自己写的函数、接口,在别的cpp里面能补全吗?我的只能补全系统函数,比如能补全string的函数,却不能补全我自己写的类
2013年10月10日回复顶转发

cloudzu你可以在Vim中执行:YcmDiags,看一下报什么样的错误信息?如果是找不到include file,你就需要在ycm_extra_config.py 中添加路径。
2013年10月11日回复顶转发


hominlinx我看了看你的ycm_extra_conf.py,需要自己设置flags,但是:
1、"-I"跟“-isystem”有啥不同啊?
2、‘-I’后面是不是将工程的根路径写上吗?你们貌似不是,而是写到了最后一级啊?
2013年10月10日回复顶转发

cloudzu1. 我们一般把“-I”用作自己的代码,"-isystem"用作第三代码。这样编译代码的时候,第三方代码编译时的warning,就不会显示出来,只需要专注在自己写的代码。
2. 我们的makefile比较复杂,不同部分出自不同的人,写include的风格也有些不同,有人就喜欢在include后加上很长的路径,有人则认为路径配置在makefile中,include的时候只需要文件名就好了。
2013年10月11日回复顶转发

hominlinx你好,请问你一般将你的ycm_extra_conf.py放置的什么路径下面啊?是:.vim/bundle/YouCompleteMe/cpp/ycm/下面吗?
还是自己的工程下面啊?
2013年11月2日回复顶转发

cloudzu我一般是放在工程目录下面的,因为我的ycm_extra_config.py里面有很多针对工程的相对路径
2013年11月3日回复顶转发

hominlinx能给我一个开源的工程参考一下吗?谢谢 我现在在学opengl
2013年11月3日回复顶转发


hominlinx还有一个问题:我现在在使用opengl,在ycm_extra_conf.py里面也加入了相应的flag,但是依然没有补全,不过我如果在写代码时,前面加入“::”,他就会补全,这是为啥啊?谢谢
2013年11月2日回复顶转发


冷风一夜你好,安装了YCM但是对Python文档不工作,下面显示“找不到补全模式”,感觉好奇怪。
2013年10月15日回复顶转发

cloudzu理论上YCM补全python不需要设置,可能是安装的问题,作者推荐使用vundle安装,你可以再重装试试。
2013年10月16日回复顶转发


wych补全很傻,写ruby 敲class 补全里居然有php XX
2013年11月14日回复顶转发


丶因为YCM 需要tag文件支持嘛?
2013年12月1日回复顶转发

cloudzu不需要tag,C/C++需要clang支持
2013年12月3日回复顶转发



housansan函数能自动补全参数不?
2013年12月2日回复顶转发

cloudzu不知道你说自动补全参数指的什么。补全函数时会有参数提示,上面的gif中有演示
2013年12月3日回复顶转发

housansan恩。。看到了,没看仔细,,是我想要的功能
2013年12月5日回复顶转发


dreamgoes" Installing bundles to /home/melo/.vi|
m/bundle
. Bundle 'gmarik/vundle'
> Bundle 'Valloric/YouCompleteMe'
Bundle 'scrooloose/syntastic'
Bundle 'tpope/vim-fugitive'
Bundle 'Lokaltog/vim-easymotion'
Bundle 'rstacruz/sparkup'
Bundle 'L9'
Bundle 'FuzzyFinder'
Bundle 'git://git.wincent.com/command
t.git'
Helptags

Processing 'Valloric/YouCompleteMe'
我安装插件一直是这个状态(处理安装第一个插件不动), 请问楼主这是什么原因?
2013年12月5日回复顶转发


Silent_hi你好,我想问一下你知道不知道YCM那个黑色配色哪里有,为什么要变量和方法名配色是一起的分不开,还有装了YCM之后,你普通的if for while自动补全怎么做到的,谢谢了。我是VIM菜鸟,正在学习,希望能得到你的回复。
2013年12月19日回复顶转发

cloudzu我的color scheme 是molokai(https://github.com/tomasr/molokai),补全if for while是用的UltiSnip (https://github.com/SirVer/ultisnips)
2013年12月20日回复顶转发

Silent_hi好的收到了,我试试,QQQ。
2013年12月21日回复顶转发



Tao Honker请教 cloudzu,如何用whitelist/blacklist来让ycm不要在每次打开vim时都问问题?看它的doc没怎么看懂,我现在是指定一个ycm_global_ycm_extra_conf的方式来让它不叫唤的。
2013年12月21日回复顶转发


nob0dy我这里在补全一个函数的时候好像就只补全了函数名,不会出现函数名后面的括号,也无法补全函数的参数啊?
2013年12月24日回复顶转发


housansan开发linux驱动,需要怎么添加?能否解释下 ycm_extra_conf.py含义
2013年12月28日回复顶转发


junevimer你好,我的YCM安装完以后,写了main.c,test.c,test.h.3个文件测试.函数test1()申明在test.h中.定义在test.c中,在main中想跳转到函数test1(),但是只能跳到申明处,想跳转到定义处时,提示 RuntimeError: Can't jump to definition.是不是还需要配置什么?
2月11日回复顶转发


忆是星河您好,我安装ycm后,那个ycmd的服务老是打开失败,下面是给的提示
HTTPConnectionPool(host='localhost', port=51092): Max retries exceeded with url: /event_no
tification (Caused by <class 'socket.error'>: [Errno 111] 拒绝连接)
An error occured. This is either a bug in UltiSnips or a bug in a
snippet definition. If you think this is a bug, please report it to
https://github.com/SirVer/ultisnips/issues/new.

Following is the full stack trace:
Traceback (most recent call last):
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py", line 48, in wrapper
return func(self, *args, **kwds)
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py", line 123, in expand_or_jump
rv = self._try_expand()
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py", line 457, in _try_expand
snippets = self._snips(before, False)
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py", line 397, in _snips
for snippet in source.get_snippets(filetypes, before, possible):
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_base.py", line 36, in get_snippets
self._ensure_loaded(ft, set())
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_base.py", line 54, in _ensure_loaded
if self._needs_update(ft):
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_base.py", line 63, in _needs_update
existing_files = self._get_all_snippet_files_for(ft)
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/ultisnips.py", line 149, in _get_all_snippet_files_for
return set(base_snippet_files_for(ft))
File "/home/sunqiang/.vim/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/ultisnips.py", line 48, in base_snippet_files_for
"You have 'snippets' in UltiSnipsSnippetDirectories. This "
RuntimeError: You have 'snippets' in UltiSnipsSnippetDirectories. This directory is reserved for snipMate snippets. Use another directory for UltiSnips snippets.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编译器 编辑器 python