为YCM配置ycm_extra_conf.py脚本

前言

YCM应该是vim补全的标配了,关于配置可以直接阅读官方README文件,写得十分详细,但是需要点耐心。
我之前写过Ubuntu 16.04 64位安装YouCompleteMe,主要针对的是apt-get安装的vim版本不支持YCM的python引擎问题,所以得手动编译vim源码。不过关于YCM的配置文件很多都是直接照抄的,有些用法没有理解,最近想要看看开源代码,由于include的头文件很多都把项目目录作为包含目录,而YCM配置文件缺只使用了系统目录,所以无法进行代码跳转和补全。

修改YCM配置文件

YCM配置文件的路径在.vimrc文件中定义,比如我的配置是
let g:ycm_global_ycm_extra_conf='~/.ycm_extra_conf.py'
用的默认命名ycm_extra_conf.py,直接扔到了用户主目录下,修改文件名和路径都是可以的。该配置文件的核心就是修改flags变量。

flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-DNDEBUG',
'-std=c++11',
'-x',
'c++',
'-I',
'/usr/include',
'-isystem',
'/usr/lib/gcc/x86_64-linux-gnu/5/include',
'-isystem',
'/usr/include/x86_64-linux-gnu',
'-isystem'
'/usr/include/c++/5',
'-isystem',
'/usr/include/c++/5/bits'
]

可以看到flags是一个列表,参数是和gcc的参数一致。
比如对下面的示例项目

$ tree sample/
sample/
├── include
│   └── foo.h
└── src
    └── main.cc

其中main.cc的include代码如下


可以发现vim提示foo.h无法找到,但是我们可以这样编译该文件
g++ main.cc -isystem $HOME/sample/include
也可以用下列编译方式
g++ main.cc -I $HOME/sample/include

man gcc查看手册,找到-isystem的说明

       -isystem dir
           Search dir for header files, after all directories specified by -I
           but before the standard system directories. 

搜索头文件的顺序是:-I指定目录、-isystem指定目录、标准系统目录。
OK,回顾之前flags参数的设置,一目了然,只需要在末尾添加新的-I-isystem,后接头文件目录路径即可。在python中可以定义一个变量保存用户主目录路径
home_dir = os.environ['HOME']
需要注意的细节是,flags列表最后一项的的结尾没有加逗号,如果在后面添加新项,记得加上逗号(我好几次忘记加了导致语法错误)

# 错误的代码
'/usr/include/c++/5/bits'  # 粗心大意,直接在后面换行,忘记加逗号。
'-isystem',
os.path.join(home_dir, 'sample/include')
]

拷贝YCM配置文件到项目目录

之前修改的是全局YCM配置文件,如果有多个项目,每次都修改全局配置文件的话,flags列表就会越来越长,头文件搜索目录越来越多,会影响YCM的效率,因此可以拷贝一份到项目目录下,然后再进行修改。

~/sample$ cp ~/.ycm_extra_conf.py .
~/sample$ ls -a
.  ..  include  src  .ycm_extra_conf.py

YCM配置文件的查找顺序是当前目录>上层目录>...>根目录>YCM全局目录。
然后问题来了,每次打开文件都会提示是否载入YCM配置文件。


这问题十分烦人,不过也给出了提示,想要关闭这个提示可以参考YCM文档。找到的解决方案如下
let g:ycm_confirm_extra_conf = 0
官方说明表示该选项的默认值为1是为了阻止不是由你写的YCM配置代码,比如你从网上下载一个项目,由于YCM配置文件默认是隐藏文件,所以你也不知道项目目录下包含了YCM配置文件,此时vim打开代码时就会提示你是否载入,从而提醒你项目目录里有YCM配置文件。
所以安全的做法是自己写代码时,可以把该选项设为0,其余情况下保持默认值1。

实践:阅读Linux内核源码的配置

这几天想确认下内核是否真的用do_fork来区分线程和进程,于是下载了源码来查找。首先找到kernel/fork.c,vim打开后如下所示


借助find命令来查找头文件的位置

~/linux-4.16.13$ find . -name "mm.h"
./drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
./include/linux/decompress/mm.h
./include/linux/mm.h
./include/linux/sched/mm.h
./arch/unicore32/mm/mm.h
./arch/arm/mm/mm.h
./tools/testing/scatterlist/linux/mm.h
./tools/include/linux/sched/mm.h

find默认就是递归查找,可以用maxdepth选项来控制递归最大深度,比如

~/linux-4.16.13$ find . -maxdepth 3 -name "mm.h"
./include/linux/mm.h

于是可以把YCM配置文件拷贝到linux-4.16.13目录下,修改flags如下

flags = [
# 省略之前的参数
'-isystem',
os.path.join(home_dir, 'linux-4.16.13'),
'-isystem',
os.path.join(home_dir, 'linux-4.16.13/include')
]

这里还不够,只是解决了头文件包含的问题,代码跳转时,比如光标停在task_struct,点击跳转快捷键时,发现无法跳转。这里就需要用grep命令来查找,

~/linux-4.16.13/include$ egrep -rn "struct +task_struct +{"
linux/sched.h:524:struct task_struct {

egrep即使用扩展正则表达式,内核编码风格是把左大括号和结构体名称放在一行,所以用这个正则表达式就找到了task_struct的定义。
可以用sed命令多看几行来确认下

~/linux-4.16.13/include$ sed -n '524,530p' linux/sched.h 
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /*
     * For reasons of header soup (see current_thread_info()), this
     * must be the first element of task_struct.
     */
    struct thread_info      thread_info;

嗯,定义了thread_info成员,继续把该目录加入flags中。但还是跳转不了,因为发现fork.c中并未包含linux/sched.h。这种情况暂时也没找到好的方法,只能用grep命令来手动查找。

.vimrc中的其他YCM配置选项

之前的配置文件是东抄抄西抄抄凑的,这次整理了下,给每个选项设置都加了注释。

" YouCompleteMe
" Python Semantic Completion
let g:ycm_python_binary_path = '/usr/bin/python3'
" C family Completion Path
let g:ycm_global_ycm_extra_conf='~/.ycm_extra_conf.py'
" 跳转快捷键
nnoremap <c-k> :YcmCompleter GoToDeclaration<CR>|
nnoremap <c-h> :YcmCompleter GoToDefinition<CR>| 
nnoremap <c-j> :YcmCompleter GoToDefinitionElseDeclaration<CR>|
" 停止提示是否载入本地ycm_extra_conf文件
let g:ycm_confirm_extra_conf = 0
" 语法关键字补全
let g:ycm_seed_identifiers_with_syntax = 1
" 开启 YCM 基于标签引擎
let g:ycm_collect_identifiers_from_tags_files = 1
" 从第2个键入字符就开始罗列匹配项
let g:ycm_min_num_of_chars_for_completion=2
" 在注释输入中也能补全
let g:ycm_complete_in_comments = 1
" 在字符串输入中也能补全
let g:ycm_complete_in_strings = 1
" 注释和字符串中的文字也会被收入补全
let g:ycm_collect_identifiers_from_comments_and_strings = 1
" 弹出列表时选择第1项的快捷键(默认为<TAB>和<Down>)
let g:ycm_key_list_select_completion = ['<C-n>', '<Down>']
" 弹出列表时选择前1项的快捷键(默认为<S-TAB>和<UP>)
let g:ycm_key_list_previous_completion = ['<C-p>', '<Up>']
" 主动补全, 默认为<C-Space>
"let g:ycm_key_invoke_completion = ['<C-Space>']
" 停止显示补全列表(防止列表影响视野), 可以按<C-Space>重新弹出
"let g:ycm_key_list_stop_completion = ['<C-y>']
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容