VIM开发C项目
TODO
- 插件安装
- 自动补全
- 代码检查
- 代码注释
- 代码折叠
插件安装
- Github找到vim-plug.
- Install
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
# 连接不上github,把第二行更换成https://gitee.com/lxyoucan/vim-plug.git
- Set
#~/.vimrc中加入以下内容
call plug#begin('~/.vim/plugged')
"emmet for wait html"
Plug 'mattn/emmet-vim'
call plug#end()
- Install plugins
- 要新安装插件时在
plug#begin('~/.vim/plugged')
和plug#end()
之间加入一行`Plug ‘github上找到的项目’。例:scrooloose/nerdtree。 - 用vim随意打开一个文件输入
:PlugInstall
。等待安装完成 - 国内克隆github太慢,就不要使用
:PlugInstall
。直接进入~/.vim/plugged/
,输入命令git clone --recursive https://gitee.com/you-complete-me/YouCompleteMe.git
- vim-plug命令:PlugInstall PlugRemove PlugUpdate …
- 要新安装插件时在
自动补全和代码检查
- 自动补全使用YouCompleteMe
- 安装方式
- 最新版本的YouCompleteMe的.ycm_extra_conf.py的配置方式改了,所以要自己加FlagsForFile方法。.ycm_extra_conf.py的开头设置如下:
flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-ferror-limit=10000',
'-DNDEBUG',
'-std=c99',
'-xc',
'-isystem',
'/usr/include/',
]
SOURCE_EXTENSIONS = [
'.cpp',
'.cxx',
'.cc',
'.c',
]
def FlagsForFile( filename, **kwargs ):
return {
'flags': flags,
'do_cache': True
}
- 同样因为墙的原因国内下载libclang非常慢,所以建议编译时加入–system-libclang选项。
- ycmd头文件设置
- ycmd可以使用.ycm_extra_conf.py文件设置当前项目包含头文件搜索目录
- 复制~/.vim/plugg/YouCompleteMe/.ycm_extra_conf.py到当前项目根目录
- 更改ycm_extra_conf.py flags 数组,如果没有可以增加。网上很多模板
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++',
'-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/local/include'
]
c++ 可以改为C,-isystem后面的一行就是指定头文件搜索目录的,可以添加多个
- 一个问题:
- 如果这里用相对路径,子目录中的文件打开就不能正确找到头文件
- 如果用绝对路径,把这个项目移动到别的目录或电脑就完全不可能正确运行
- 解决方案:
当前设置文件是python脚本,因此可以使用os
获取当前文件所在目录,对于项目而言也就是项目根目录。再从这个根目录出发,就可以设置好了import os import ycm_core #错误作法,这样看似是获取的当前目录。实际ycmd运行时不能获取到项目根目录,应该是会等到YCMD插件的位置,所以是不行的。 #pwd = os.getcwd() + "/src/includes"; #正确版本 pwd = os.path.dirname(os.path.abspath(__file__)) + "/src/includes" # 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++', '-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/local/include' ] # 加入新获取的头文件搜索目录 flags.append('-isystem') flags.append(pwd)
-
ALE搜索头文件目录
- ALE头文件根据项目设定可以先安装一个vim插件–
vim-projectlocal
. github搜索,用前面的vim-plug安装就可以了。 - 当前项目根目录新建一个.vimrc
let g:ale_c++_clang_options="-I后面就是要自定义的搜索目录"
- 同样的和
.ycm_extra_conf.py
中一样,如果写相对路径和绝对路径都容易出现问题。这次不是python脚本,但是vimScript,同样也是脚本语言:
# ./.vimrc let pwd = expand("<sfile>:p:h") let g:ale_c++_clang_options="-I" . pwd . "/src/includes" # 这里和python不同不能用'+',要使用'.' # ycmd默认加载.ycm_extra_conf.py时要求你确认,就是每次打开文件要你输入O 。可以使用下面选项关闭确认,默认就加载了 let g:ycm_confirm_extra_conf = 0
这里有个坑是ALE文档上说是是用g:ale_pattern_options, 但中间的pattern没说要根据不同语言和不同编绎器改变。比如用于C语言的gcc:
g:ale_c_gcc_options=
,用于C++的Clang:g:ale_c++_clang_options=
- 上面的ycmd和ALE设置好以后,用vim打开这个根目录下的所有c或c++文件都会加入指定的头文件搜索目录,不会出现找不到头文件的问题,这个问题一直是一个C/C++项目的大问题
- ALE头文件根据项目设定可以先安装一个vim插件–
代码注释
- 也是一个插件搞定-- Plug ‘scrooloose/nerdcommenter’
- 都不用配置直接使用默认就可以
- 使用:
- cc用于注释本行或选中行
- cu用于取消本行或选中行
- 只要没有更改过就是反斜杠’\’
代码折叠
- .vimrc中加入一行
set fdm=marker
"有6个选项:
"manual 手工定义折叠
"indent 更多的缩进表示更高级别的折叠
"expr 用表达式来定义折叠
"syntax 用语法高亮来定义折叠
"diff 对没有更改的文本进行折叠
"marker 对文中的标志折叠
- 折叠命令
zf 手动创建折叠
zc 折叠光标所在处(不一定有效,但是条件不清楚,有括号的时候可以成功)
zC 对所在范围内所有嵌套的折叠点进行折叠
zo 将当前折叠打开
zO 对所在范围内所有嵌套的折叠点展开
zm 折叠所有层次(依层次折叠)
zM 折叠所有 (依层次折叠),作用和zm 同,但对于巢状折叠亦有作用
zn 打开全文的所有折叠。 fold none。
zN 这是zn 的相对指令,回复所有的折叠。zr 打开所有折叠层次(依层次打开)
zR 打开所有折叠 (依层次打开),作用和zr 同,但会打开折叠中又还有折叠的所有折叠。
zi 切换折叠与不折叠指令
zj 向下移动。到达下一个折叠的开始处。关闭的折叠也被计入
zk 向上移动到前一折叠的结束处。关闭的折叠也被计入
zd 删除折叠(其实在折叠上面dd就可以删除了)
zD 删除所有折叠
[z 到当前打开的折叠的开始处。
]z 到当前打开的折叠的末尾处。
有上以上工具vim完全可以胜任第一编辑器的地位。如果加上Cmake,一个大型的C/C++也是完全没有问题。Cmake构建项目,cmake可以指定安装库目录,执行文件编绎位置。所以完全可以使用cmake管理一个C/C++项目,还可以进行单元测试。
使用工具总结
- 支持python3的vim
- clang用于代码检测服务
- YouCompleteMe-Vim插件用于代码补全。YouCompleteMe有个代码定义跳转很好用,可以在.vimrc中加入
"使用'\f'就可以完成跳转
nmap <leader>f :YcmCompleter GoTo <CR>
"加一个YouCompleteMe自带的代码检测工具开关,ycmd自带的代码检测是同步检测,就是你输入就检测。ALE可以你输入完成保存时才一次性检测,我比较喜欢ALE的保存检测方式。ALE还有代码修复和代码缩进调整功能,有点意思有兴趣可以研究研究。
let g:ycm_show_diagnostics_ui = 0
- nerdcommenter是一个代码注释插件,简单好用
- vim-projectlocal是一个项目vim配置文件项目化的插件,可以在项目根目录和子目录中设置不同的.vimrc。这里主要用于设置ALE头文件搜索目录,找到头文件。
- 除以上插件和工具,还用到一些插件和工具。这里不做具体说明,只给一个目录:
- ctags(这是一个软件项目,使用yum或apt安装。ycmd要求必须安装)
- vim-scripts/taglist.vim插件
- scrooloose/nerdtree插件(目录树插件,可以实现ide显示目录树功能)