转自:http://blog.jobbole.com/58978/

可能会有一段时间写linxu,免不了用vim,留着,找时间实操之

原文出处: marchtea 的博客

第一次听说这个插件还是在偶然的情况下看到别人的博客,听说了这个插件的大名。本来打算在实训期间来完成安装的,无奈网实在不给力,也就拖到了回家的时候。在开始准备工作的时候就了解到这个插件不是很容易安装,安装的时候果然名不虚传。(关于这方面的内容,请查看另一篇文章)不过,有付出总有回报,安装之后用上这个插件,真心为这个插件的强大所折服。

那这个插件有何不同?

YouCompleteMe的特别之处

基于语义补全

总所周知,Vim是一款文本编辑器。也就是说,其最基础的工作就是编辑文本,不管该文本的内容是什么。在Vim被程序员所使用后,其慢慢的被肩负了与IDE一样的工作,文本自动补全(ie.acp,omnicppcompleter),代码检查(Syntastic)等等工作。

针对文本自动补全这个功能来说,主要有两种实现方式。

  • 基于文本

我们常用的omnicppcompleter,acp,vim自带的c-x, c-n的实现方式就是基于文本。更通俗的说法,其实就是一个字:

其通过文本进行一些正则表达式的匹配,再根据生成的tags(利用ctags生成)来实现自动补全的效果。

  • 基于语义

顾名思义,其是通过分析源文件,经过语法分析以后进行补全。由于对源文件进行分析,基于语义的补全可以做到很精确。但是这显然是vim所不可能支持的。而且经过这么多年发展,由于语法分析有很高的难度,也一直没有合适的工具出现。直到,由apple支持的clang/llvm横空出世。YouCompleteMe也正是在clang/llvm的基础上进行构建的。

整合实现了多种插件
  • clang_complete
  • AutoComplPop
  • Supertab
  • neocomplcache
  • Syntastic(类似功能,仅仅针对c/c++/obj-c代码)
支持语言
  • c
  • c++
  • obj-c
  • c#
  • python

对于其他的语言,会调用vim设置的omnifunc来匹配,因此同样支持php,ruby等语言。

已知的有 * javascript —-tern_for_vim * ruby/java —-eclim

使用效果图


使用感受
  • 和IDE一样,自动补全,
  • 根据include的文件进行补全
  • 不用再蹩脚的生成tags
  • 补全非常精准,而且速度很快,不会有延迟(以前在大项目上,acp用起来实在是很卡)
  • 支持类似tags的跳转,跳到定义处以及使用处
  • 出错提示很智能,并且用起来真的是如丝般柔滑,不用输入:w进行强制检测

安装

说完了那么多好处,就要说到安装了。不同于以往其他vim插件,YCM是一款编译型的插件。在下载完后,需要手动编译后才能使用。对应其他的插件来说,仅仅就是把.vim的文件丢到相应文件夹下就可以。而这也加大了使用YCM的难度。

安装准备
  • 最新版的Vim(7.3.584+),编译时添加+python标志(已经安装的可以通过vim --version查看)
  • cmake(mac可以通过homebrew安装,brew install cmake,ubuntu可以通过sudo apt-get install cmake)
  • 安装vundle插件,用于安装管理vim的插件
mac下快速安装

.vimrc中添加下列代码

Shell

1

Bundle 'Valloric/YouCompleteMe'

保存退出后打开vim,在正常模式下输入

Shell

1

:BundleInstall

等待vundle将YouCompleteMe安装完成

而后进行编译安装:

Shell

1

2

cd ~/.vim/bundle/YouCompleteMe

./install --clang-completer

如果不需要c-family的补全,可以去掉--clang-completer。如果需要c#的补全,请加上--omnisharp-completer。

正常来说,YCM会去下载clang的包,如果已经有,也可以用系统--system-libclang。

就这样,安装结束。打开vim,如果没有提示YCM未编译,则说明安装已经成功了。

手动编译安装

安装的脚本并不是什么时候都好用,至少对我来说是这样的。安装完之后出现了问题,参考issue#809

在用:BundleInstall安装完成或者使用

Shell

1

git clone --recursive https://github.com/Valloric/YouCompleteMe.git

获取最新的仓库,而后使用git submodule update --init --recursive确认仓库的完整性后,开始安装流程。

  1. 下载最新的clang二进制文件 YCM要求clang版本 > 3.2,一般来说都是下载最新的
  2. 安装python-dev.(ubuntu下使用sudo apt-get install python-dev,mac下默认提供,否则请安装command line tools)
  3. 编译

    Shell

    1

    2

    3

    4

    cd ~

    mkdir ycm_build

    cd ycm_build

    cmake -G “Unix Makefiles” -DPATH_TO_LLVM_ROOT=~/ycm_temp/llvm_root_dir . ~/.vim/bundle/YouCompleteMe/cpp make ycm_support_libs

    这里需要注意的是,~/ycm_temp/llvm_root_dir中包含的是根据第一步下载的压缩包解压出来的内容(包括include, bin等等文件)。

这样就完成了,开始感受YCM提供的完全不逊色于大型IDE所提供的自动补全功能吧。

配置

不同于很多vim插件,YCM首先需要编译,另外还需要有配置。在vim启动后,YCM会找寻当前路径以及上层路径的.ycm_extra_conf.py.在~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py中提供了默认的模板。也可以参考我的(就在模板上改改而已)。不过这个解决了标准库提示找不到的问题。

一般来说,我会在~目录下放一个默认的模板,而后再根据不同的项目在当前目录下再拷贝个.ycm_extra_conf.py。

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

# This file is NOT licensed under the GPLv3, which is the license for the rest

# of YouCompleteMe.

#

# Here's the license text for this file:

#

# This is free and unencumbered software released into the public domain.

#

# Anyone is free to copy, modify, publish, use, compile, sell, or

# distribute this software, either in source code form or as a compiled

# binary, for any purpose, commercial or non-commercial, and by any

# means.

#

# In jurisdictions that recognize copyright laws, the author or authors

# of this software dedicate any and all copyright interest in the

# software to the public domain. We make this dedication for the benefit

# of the public at large and to the detriment of our heirs and

# successors. We intend this dedication to be an overt act of

# relinquishment in perpetuity of all present and future rights to this

# software under copyright law.

#

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR

# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,

# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR

# OTHER DEALINGS IN THE SOFTWARE.

#

# For more information, please refer to <http://unlicense.org/>

import os

import ycm_core

# These are the compilation flags that will be used in case there's no

# compilation database set (by default, one is not set).

# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.

flags = [

'-Wall',

'-Wextra',

#'-Werror',

#'-Wc++98-compat',

'-Wno-long-long',

'-Wno-variadic-macros',

'-fexceptions',

'-stdlib=libc++',

# THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't know which

# language to use when compiling headers. So it will guess. Badly. So C++

# headers will be compiled as C headers. You don't want that so ALWAYS specify

# a "-std=<something>".

# For a C project, you would set this to something like 'c99' instead of

# 'c++11'.

'-std=c++11',

# ...and the same thing goes for the magic -x option which specifies the

# language that the files to be compiled are written in. This is mostly

# relevant for c++ headers.

# For a C project, you would set this to 'c' instead of 'c++'.

'-x',

'c++',

'-I',

'.',

'-isystem',

'/usr/include',

'-isystem',

'/usr/local/include',

'-isystem',

'/Library/Developer/CommandLineTools/usr/include',

'-isystem',

'/Library/Developer/CommandLineTools/usr/bin/../lib/c++/v1',

]

# Set this to the absolute path to the folder (NOT the file!) containing the

# compile_commands.json file to use that instead of 'flags'. See here for

# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html

#

# Most projects will NOT need to set this to anything; you can just change the

# 'flags' list of compilation flags. Notice that YCM itself uses that approach.

compilation_database_folder = ''

if os.path.exists( compilation_database_folder ):

database = ycm_core.CompilationDatabase( compilation_database_folder )

else:

database = None

SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]

def DirectoryOfThisScript():

return os.path.dirname( os.path.abspath( __file__ ) )

def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):

if not working_directory:

return list( flags )

new_flags = []

make_next_absolute = False

path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]

for flag in flags:

new_flag = flag

if make_next_absolute:

make_next_absolute = False

if not flag.startswith( '/' ):

new_flag = os.path.join( working_directory, flag )

for path_flag in path_flags:

if flag == path_flag:

make_next_absolute = True

break

if flag.startswith( path_flag ):

path = flag[ len( path_flag ): ]

new_flag = path_flag + os.path.join( working_directory, path )

break

if new_flag:

new_flags.append( new_flag )

return new_flags

def IsHeaderFile( filename ):

extension = os.path.splitext( filename )[ 1 ]

return extension in [ '.h', '.hxx', '.hpp', '.hh' ]

def GetCompilationInfoForFile( filename ):

# The compilation_commands.json file generated by CMake does not have entries

# for header files. So we do our best by asking the db for flags for a

# corresponding source file, if any. If one exists, the flags for that file

# should be good enough.

if IsHeaderFile( filename ):

basename = os.path.splitext( filename )[ 0 ]

for extension in SOURCE_EXTENSIONS:

replacement_file = basename + extension

if os.path.exists( replacement_file ):

compilation_info = database.GetCompilationInfoForFile(

replacement_file )

if compilation_info.compiler_flags_:

return compilation_info

return None

return database.GetCompilationInfoForFile( filename )

def FlagsForFile( filename, **kwargs ):

if database:

# Bear in mind that compilation_info.compiler_flags_ does NOT return a

# python list, but a "list-like" StringVec object

compilation_info = GetCompilationInfoForFile( filename )

if not compilation_info:

return None

final_flags = MakeRelativePathsInFlagsAbsolute(

compilation_info.compiler_flags_,

compilation_info.compiler_working_dir_ )

# NOTE: This is just for YouCompleteMe; it's highly likely that your project

# does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR

# ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT.

#try:

#  final_flags.remove( '-stdlib=libc++' )

#except ValueError:

#  pass

else:

relative_to = DirectoryOfThisScript()

final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )

return {

'flags': final_flags,

'do_cache': True

}

YouCompleteMe提供的其他功能

YCM除了提供了基本的补全功能,自动提示错误的功能外,还提供了类似tags的功能:

  • 跳转到定义GoToDefinition
  • 跳转到声明GoToDeclaration
  • 以及两者的合体GoToDefinitionElseDeclaration

可以在.vimrc中配置相应的快捷键。

Shell

1

2

3

nnoremap <leader>gl :YcmCompleter GoToDeclaration<CR>

nnoremap <leader>gf :YcmCompleter GoToDefinition<CR>

nnoremap <leader>gg :YcmCompleter GoToDefinitionElseDeclaration<CR>

另外,YCM也提供了丰富的配置选项,同样在.vimrc中配置。具体请参考

Shell

1

2

let g:ycm_error_symbol = '>>'

let g:ycm_warning_symbol = '>*'

同时,YCM可以打开location-list来显示警告和错误的信息:YcmDiags。个人关于ycm的配置如下:

Shell

1

2

3

4

5

6

7

" for ycm

let g:ycm_error_symbol = '>>'

let g:ycm_warning_symbol = '>*'

nnoremap <leader>gl :YcmCompleter GoToDeclaration<CR>

nnoremap <leader>gf :YcmCompleter GoToDefinition<CR>

nnoremap <leader>gg :YcmCompleter GoToDefinitionElseDeclaration<CR>

nmap <F4> :YcmDiags<CR>

YCM提供的跳跃功能采用了vim的jumplist,往前跳和往后跳的快捷键为Ctrl+O以及Ctrl+I。

总结

YouCompleteMe是我用过的最爽的一个自动补全的插件了。之前使用acp时,遇到大文件基本上就卡死了,以至于都不怎么敢使用。由于YCM使用的时C/S结构,部分使用vim脚本编写,部分认为原生代码,使得跑起来速度飞快。

抛弃Vim自带的坑爹的补全吧,抛弃ctags吧,抛弃cscope吧,YCM才是终极补全神器。

在安装过程中,我也遇到了不少的坑。一会会发一篇解决这些坑的文章。

最后祝大家码年顺利,一码平川,码到功成。

Vim自动补全神器:YouCompleteMe(转)的更多相关文章

  1. Vim自动补全神器–YouCompleteMe

    YouCompleteMe的特别之处 基于语义补全 总所周知,Vim是一款文本编辑器.也就是说,其最基础的工作就是编辑文本,而不管该文本的内容是什么.在Vim被程序员所使用后,其慢慢的被肩负了与IDE ...

  2. Vim自动补全神器YouCompleteMe的配置

    简介:YouCompleteMe号称Vim的自动补全神器,该项目在github的地址:YouCompleteMe:以下在10.0.1 build-1379776平台配置完成 插件安装操作: 1.确保V ...

  3. Vim自动补全神器–YouCompleteMe

    一.简介 YouCompleteMe是Vim的自动补全插件,与同类插件相比,具有如下优势 1.基于语义补全 2.整合实现了多种插件 clang_complete.AutoComplPop .Super ...

  4. 【转】Vim自动补全插件----YouCompleteMe安装与配置

    原文网址:http://www.cnblogs.com/zhongcq/p/3630047.html 使用Vim编写程序少不了使用自动补全插件,在Linux下有没有类似VS中的Visual Assis ...

  5. Vim自动补全插件----YouCompleteMe安装与配置

    Vim自动补全插件----YouCompleteMe安装与配置 使用Vim编写程序少不了使用自动补全插件,在Linux下有没有类似VS中的Visual Assist X这么方便快捷的补全插件呢?以前用 ...

  6. Vim自动补全神器:YouCompleteMe

    第一次听说这个插件还是在偶然的情况下看到别人的博客,听说了这个插件的大名.本来打算在实训期间来完成安装的,无奈网实在不给力,也就拖到了回家的时候.在开始准备工作的时候就了解到这个插件不是很容易安装,安 ...

  7. (转)Vim自动补全神器:YouCompleteMe

    原文出处:http://blog.jobbole.com/58978/ 第一次听说这个插件还是在偶然的情况下看到别人的博客,听说了这个插件的大名.本来打算在实训期间来完成安装的,无奈网实在不给力,也就 ...

  8. vim自动补全插件YouCompleteMe

    前言 Valloric/YouCompleteMe可以说是vim安装最复杂的插件之一,但是一旦装好,却又是非常好用的.YouCompleteMe简称ycm 在安装折腾的过程中,我再一次的体会到,除了官 ...

  9. CentOS7 Vim自动补全插件----YouCompleteMe安装与配置

    最近刚装了新系统CentOS7,想要把编码环境配置一下,使用Vim编写程序少不了使用自动补全插件,我以前用的是neocomplcache+code_complete+omnicppcomplete.但 ...

随机推荐

  1. Delphi 7下使用Log4Delphi 0.8日志组件

    Log4Delphi是一个开放源码项目,旨在制作用于Borland的Delphi高质量实用的日志套件,是基于Apache Software Foundation的log4j包. 安装:         ...

  2. RDD.scala(源码)

    ---- map. --- flatMap.fliter.distinct.repartition.coalesce.sample.randomSplit.randomSampleWithRange. ...

  3. ReactiveCocoa框架学习1

    写block直接使用inline block的声明类型 在ARC中使用strong,如果不使用strong,则会被销毁 在非ARC中使用copy block在开发中的使用场景 把block保存到对象中 ...

  4. python 基础干货 01

    赋值的实现 a = 'abc' 1. 在内存中创建了'abc'字符串; 2. 在内存中创建了一个名为 a 的变量, 并把它指向刚才创建的'abc', 也就是a中保存着字符串的地址. b = a, 创建 ...

  5. jquerymobile知识点:实现toolbar下方显示,自定义图标!

    css: .nav-glyphish-example .ui-btn .ui-btn-inner { padding-top: 40px !important; } .nav-glyphish-exa ...

  6. W5500问题集锦(持续更新中)

    在"WIZnet杯"以太网技术竞赛中,有非常多參赛者在使用中对W5500有各种各样的疑问,对于这款WIZnet新推出的以太网芯片,使用中大家是不是也一样存在下面问题呢?来看一看: ...

  7. android账号与同步之同步实现

    上一篇博文我先介绍了账号与同步的账号管理,这篇就介绍一下还有一部分.就是android给提供的sync同步机制的使用. 事实上sync机制的使用和上一篇博文中介绍的账号管理非常类似,也是基于binde ...

  8. 使用like时left outer join和inner join的区别

    --select top 10000 * into #s from search set statistics time on set statistics io on select userId,c ...

  9. 重新格式化namenode后,出现java.io.IOException Incompatible clusterIDs

    错误: java.io.IOException: Incompatible clusterIDs in /data/dfs/data: namenode clusterID = CID-d1448b9 ...

  10. Spring XD 1.1 M2 and 1.0.3 released---support kafka

    官方地址:http://spring.io/blog/2014/12/23/spring-xd-1-1-m2-and-1-0-3-released On behalf of the Spring XD ...