Vim自动补全插件YouCompleteMe安装

@author zhanjzh

YouCompleteMe

简称YCM,使用vim编程的人应该都有所耳闻,YCM作为Vim的补全插件真的是神器。

一般情况下,我使用vscode来编程,vscode本身就已经有很不错的补全插件,但是在进行cuda编程时,很无奈的发现vscode只有一个很残缺的vscode-cudacpp 插件。为什么说残缺呢,是因为这个插件能提供的功能只有.cu 文件中对cuda 语法高亮,支持的语法补全都是缩写,只支持很少数的一部分函数,并且没有函数提示。

相比之下,vim 下的YouCompleteMe就表现得十分优秀。

前提条件

安装YCM是有版本前提的,

  1. vim版本要8.0 或者以上(最新)
  2. 自己安装 git 工具包
  3. vim支持 python2或者 python3

安装过程

在网上找到了不止一个版本的安装博客,翻来翻去都试了一下,大致的方法有下面几种:

  • 使用系统自带的clang
  • 使用YCM自己下载的clang
  • 使用自己编译的clang

无论哪种安装之后都不太行,YCM好用是好用,安装是真的坑。

官网README的安装教程: readme

我的系统为 Ubuntu

1. 配置vim的插件管理器 vundle

~/.vim 目录下,先自行下载vundle 文件:

git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle 

修改vim的配置文件~/.vimrc (第一次使用vim的人请自行创建)

set nocompatible
"filetype off
set rtp+=~/.vim/bundle/vundle
call vundle#begin()
Bundle 'gmarik/vundle'
Plugin 'Valloric/YouCompleteMe'
"Brief help of vundle
    ":BundleList
    ":BundleInstall
    ":BundleSearch
    ":BundleClean
    ":help vundle
"End brief help

call vundle#end()

2. 使用vundle安装YCM

第一步修改配置文件后退出重新进入vim ,在vim 下执行BundleInstall .

具体步骤:按下Esc 键,shift + ; 按出 : ,输入BundleInstall

等待YCM安装完毕之后,在目录 ~/.vim/bundle/ 下应该会看到有 YouCompleteMe 这个目录。

3. 配置YCM的自动补全

主要配置的是 C和C++ 的自动补全。

按照官网的安装步骤,下面应该执行:

cd ~/.vim/bundle/YouCompleteMe
python3 install.py --all

然而很遗憾,如果直接按照这个步骤来执行在下载 clang 时会报出类似这个错误:

for file: [/home/irvinglwj/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/../clang_archives/clang+llvm-3.9.0-x86_64-opensuse13.2.tar.xz]
  expected hash: [9153b473dc37d2e21a260231e90e43b97aba1dff5d27f14c947815a90fbdc8d7]
    actual hash: [e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855]
         status: [7;"Couldn't connect to server"]

意思是下载的hash不匹配。网上查了信息后有网友说原因是这个:clang官网地址迁移,但是安装包还是使用的旧的地址,因此会解析失败。

既然下载失败那就只能自行编译或者加上 --system-libclang 参数

但是经常会报出YCM server shut down 之类的奇妙错误。下面我说一下我的做法:

  1. 自行下载对应的 clang + llvm 安装包,没记错的话我是在这里下载的: clang+llvm7.0
  2. 将下载完的压缩包放入~/.vim/bundle/YouCompleteMe/third_party/ycmd/clang_archives 目录下
 cp ~/Downloads/libclang-7.0.0-x86_64-unknown-linux-gnu.tar.bz2 ~/.vim/bundle/YouCompleteMe/third_party/ycmd/clang_archives
  1. 执行官网的安装命令:
cd ~/.vim/bundle/YouCompleteMe
python3 install.py --clang-completer

如果执行 --all 的话在配置c# 补全时会出现一些错误,但是我目前不需要c# 的补全,因此没去管,另外YCM默认是有python补全的。

到目前位置应该安装完,重新进入vim会提示没有配置文件.ycm_extra_conf.py ,下面会说一下.ycm_extra_conf.py 的配置。

4. 后续配置

复制.ycm_extra_conf.py 文件

cp ~/.vim/bundle/YouCompleteMe/third_party/ycmd/.ycm_extra_conf.py ~/.vim

~/.vimrc 添加配置:

let g:ycm_global_ycm_extra_conf='~/.vim/.ycm_extra_conf.py'

这之后需要配置C++ 和 C 或者 cuda 的头文件所在地

我的.ycm_extra_conf.py 文件如下:

# Copyright (C) 2014 Google Inc.
#
# This file is part of ycmd.
#
# ycmd is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ycmd is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ycmd.  If not, see <http://www.gnu.org/licenses/>.

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',
'-fexceptions',
'-DNDEBUG',
# 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++',
'-isystem',
'/usr/include',
'-isystem',
'/usr/local/include',
#'-isystem',
#'/usr/include/c++/7.3.0',
'-isystem',
'/usr/include/c++/4.8',
'-isystem',
'/usr/local/cuda-9.0/include',
'-isystem',
'/usr/local/cuda',
'-isystem',
'/usr/lib/gcc/x86_64-linux-gnu/4.8',
#'-isystem',
#'/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward/',
#'-isystem',
#'/usr/include/clang/6.0.0/include',
'-isystem',
'/usr/include/x86_64-linux-gnu',
#'-isystem',
#'/usr/lib/llvm-6.0/lib/clang/6.0.0/include',
#'-isystem',
#'/usr/include/clang/6.0.0/include',
'-isystem',
'/usr/include/c++/4.8'
]


# 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.
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', '.cu' ]

def DirectoryOfThisScript():
  return os.path.dirname( os.path.abspath( __file__ ) )


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 )


# This is the entry point; this function is called by ycmd to produce flags for
# a file.
def FlagsForFile( filename, **kwargs ):
  if not database:
    return {
      'flags': flags,
      'include_paths_relative_to_dir': DirectoryOfThisScript()
    }

  compilation_info = GetCompilationInfoForFile( filename )
  if not compilation_info:
    return None

  # Bear in mind that compilation_info.compiler_flags_ does NOT return a
  # python list, but a "list-like" StringVec object.
  return {
    'flags': list( compilation_info.compiler_flags_ ),
    'include_paths_relative_to_dir': compilation_info.compiler_working_dir_
  }

重要的地方只有flags 那里:

flags = [
'-Wall',
'-Wextra',
'-Werror',
'-fexceptions',
'-DNDEBUG',
'-x',
'c++',
'-isystem',
'/usr/include',
'-isystem',
'/usr/local/include',
'-isystem',
'/usr/include/c++/4.8',
'-isystem',
'/usr/local/cuda-9.0/include',
'-isystem',
'/usr/local/cuda',
'-isystem',
'/usr/lib/gcc/x86_64-linux-gnu/4.8',
'-isystem',
'/usr/include/x86_64-linux-gnu',
'-isystem',
'/usr/include/c++/4.8'
]

另外如果是跟我一样要配置cuda的补全的话,有些地方要修改一下:

SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm', '.cu' ] # 添加 .cu

配置输入两个字符就能提示:

let g:ycm_semantic_triggers={'c,cpp,python,cuda': ['re!\w{2}'] }

取消函数提示时在上方跳出的框框:

set completeopt=menu,menuone
let g:ycm_add_pre_view_to_completeopt=0

更多功能有待发掘。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值