所需即所获:像 IDE 一样使用 vim

.vimrc 文件

  • vim ~/.vimrc
    " 定义快捷键的前缀,即<Leader>
    let mapleader=";"
    """""""""""""""""""""""""""""""""
    " 开启文件类型侦测
    filetype on
    " 根据侦测到的不同类型加载对应的插件,修改.vimrc时,这个可能会影响格式
    filetype plugin on
    """"""""""""""""""""""""""""""""
    " 定义快捷键到行首和行尾
    nmap LB 0
    nmap LE $
    " 设置快捷键将选中文本块复制至系统剪贴板
    vnoremap <Leader>y "+y
    " 设置快捷键将系统剪贴板内容粘贴至 vim
    nmap <Leader>p "+p
    " 定义快捷键关闭当前分割窗口
    nmap <Leader>q :q<CR>
    " 定义快捷键保存当前窗口内容
    nmap <Leader>w :w<CR>
    " 定义快捷键保存所有窗口内容并退出 vim
    nmap <Leader>WQ :wa<CR>:q<CR>
    " 不做任何保存,直接退出 vim
    nmap <Leader>Q :qa!<CR>
    " 依次遍历子窗口
    nnoremap nw <C-W><C-W>
    " 跳转至右方的窗口
    nnoremap <Leader>lw <C-W>l
    " 跳转至左方的窗口
    nnoremap <Leader>hw <C-W>h
    " 跳转至上方的子窗口
    nnoremap <Leader>kw <C-W>k
    " 跳转至下方的子窗口
    nnoremap <Leader>jw <C-W>j
    " 定义快捷键在结对符之间跳转
    nmap <Leader>M %
    """""""""""""""""""""""""""""""
    " 开启实时搜索功能
    set incsearch
    " 搜索时大小写不敏感
    set ignorecase
    " 关闭兼容模式
    set nocompatible
    " vim 自身命令行模式智能补全
    set wildmenu

源码安装

安装依赖头文件
  • sudo apt-get install python-dev python3-dev ruby-dev libX11-dev gtk-dev gtk2-dev gtk3-dev ncurses-dev
编译源码
  • 发行套件的软件源中预编译的 vim 要么不是最新版本,要么功能有阉割,有必要升级成全功能的最新版,当然,源码安装必须滴
  • 卸载老版、下载最新版7.4:ftp://ftp.vim.org/pub/vim/unix/,解压至 ~/downloads/vim74/
  • sudo apt-get remove vim
  • cd ~/downloads/vim74/
  • ./configure –with-features=huge –enable-rubyinterp –enable-pythoninterp –with-python-config-dir=/usr/lib/python2.7/config/ –enable-perlinterp –enable-gui=gtk2 –enable-cscope –prefix=/usr –enable-luainterp
  • make VIMRUNTIMEDIR=/usr/share/vim/vim74
  • sudo make install
  • 其中,–enable-rubyinterp、–enable-pythoninterp、–enable-perlinterp、–enable-luainterp 等分别表示支持 ruby、python、perl、lua 编写的插件,–enable-gui=gtk2 表示生成 gvim,–enable-cscope 支持 cscope,–with-python-config-dir=/usr/lib/python2.7/config/ 指定 python 路径(先自行安装 python 的头文件 python-devel),这几个特性非常重要,影响后面各类插件的使用。注意,你得预先安装相关依赖库的头文件,python-devel、python3-devel、ruby-devel、libX11-devel、gtk-devel、gtk2-devel、gtk3-devel、ncurses-devel,如果缺失,源码构建过程虽不会报错,但最终生成的 vim 很可能缺失某些功能。构建完成后在 vim 中执行
  • :echo has(‘python’)
  • 若输出 1 则表示构建出的 vim 已支持 python,反之,0 则不支持

插件管理

    " 将 pathogen 自身也置于独立目录中,需指定其路径
    runtime bundle/pathogen/autoload/pathogen.vim
    " 运行 pathogen
    execute pathogen#infect()
github安装插件 以 https://github.com/dyng/ctrlsf.vim 为例
压缩包安装插件
  • mkdir ~/.vim/bundle/plugin_name/
  • vim 官网下载 plugin_name 压缩包并解压至 ~/.vim/bundle/plugin_name/ 即可,注意不要重复包含多次 plugin_name/ 目录,如,~/.vim/bundle/plugin_name/plugin_name/
  • 卸载插件,直接删除 plugin_name/ 插件目录即可
通过 pathogen 管理插件后,相较以前有几点变化
  • 切勿通过发行套件自带的软件管理工具安装任何插件,不然 .vim/ 又要混乱了;
  • pathogen 无法安装配色主题风格,只能将主题插件手工放置于 ~/.vim/colors/;
  • 安装 *.vba 类型插件:
  • :e plugin_name.vba
  • :!mkdir -p ~/.vim/bundle/plugin_name
  • :UseVimball ~/.vim/bundle/plugin_name
  • :Helptags 生成帮助文档

界面美化

csExplorer 插件,可在字符模式下不用重启即可查看效果
主题风格
    " 配色方案
    set background=dark
    colorscheme solarized
    "colorscheme molokai
    "colorscheme phd
  • 不同主题都有暗/亮色系之分
营造专注氛围 光标闪烁、滚动条、菜单栏、工具条、全屏
  • 编辑器界面展示的应全是代码,不应该有工具条、菜单、滚动条浪费空间的元素,另外,编程是种精神高度集中的脑力劳动,不应出现闪烁光标、花哨鼠标这些分散注意力的
  • vim ~/.vimrc
    " 禁止光标闪烁
    set gcr=a:block-blinkon0
    " 禁止显示滚动条
    set guioptions-=l
    set guioptions-=L
    set guioptions-=r
    set guioptions-=R
    " 禁止显示菜单和工具条
    set guioptions-=m
    set guioptions-=T
  • vim 自身无法实现全屏,必须借助第三方工具 wmctrl,一个控制窗口 XYZ 坐标、窗口尺寸的命令行工具
  • sudo apt-get install wmctrl
  • vim ~/.vimrc
    " 将外部命令 wmctrl 控制窗口最大化的命令行参数封装成一个 vim 的函数
    fun! ToggleFullscreen()
        call system("wmctrl -ir " . v:windowid . " -b toggle,fullscreen")
    endf
    " 全屏开/关快捷键
    map <silent> <F11> :call ToggleFullscreen()<CR>
    " 启动 vim 时自动全屏
    " autocmd VimEnter * call ToggleFullscreen()
  • 上面是一段简单的 vimscript 脚本,外部命令 wmctrl 及其命令行参数控制将指定窗口 windowid(即,vim)全屏,绑定快捷键 F11 实现全屏/窗口模式切换(linux 下各 GUI 软件约定使用 F11 全屏,最好遵守约定)
添加辅助信息 光标当前位置、显示行号、高亮当前行/列
  • vim ~/.vimrc
    " 总是显示状态栏
    set laststatus=2
    " 显示光标当前位置
    set ruler
    " 开启行号显示
    set number
    " 高亮显示当前行/列
    set cursorline
    set cursorcolumn
    " 高亮显示搜索结果
    set hlsearch
其他美化 字体、代码折行、状态栏风格
    " 设置 gvim 显示字体
    set guifont=YaHei\ Consolas\ Hybrid\ 11.5
    " 禁止折行
    set nowrap
    " 设置状态栏主题风格
    let g:Powerline_colorscheme='solarized256'
  • 我这样配置好以后在Gvim下才有Github里截图效果

代码分析

语法高亮
  • vim ~/.vimrc
    " 开启语法高亮功能
    syntax enable
    " 允许用指定语法高亮配色方案替换默认方案
    syntax on
STL、C++14 新增元素 语法高亮
  • mkdir -p ~/.vim/bundle/STL-Syntax/after/syntax/cpp/
  • 下载stl.vim到上面新建的目录里
代码缩进 多个空格、显示为细条
  • vim ~./vimrc
    " 自适应不同语言的智能缩进
    filetype indent on
    " 将制表符扩展为空格
    set expandtab
    " 设置编辑时制表符占用空格数
    set tabstop=4
    " 设置格式化时制表符占用空格数
    set shiftwidth=4
    " 让 vim 把连续数量的空格视为一个制表符
    set softtabstop=4
  • expandtab,把制表符转换为多个空格,具体空格数量参考 tabstop 和 shiftwidth 变量;
  • tabstop 与 shiftwidth 是有区别的。tabstop 指定我们在插入模式下输入一个制表符占据的空格数量,linux 内核编码规范建议是 8,看个人需要;shiftwidth 指定在进行缩进格式化源码时制表符占据的空格数。所谓缩进格式化,指的是通过 vim 命令由 vim 自动对源码进行缩进处理,比如其他人的代码不满足你的缩进要求,你就可以对其进行缩进格式化。缩进格式化,需要先选中指定行,要么键入 = 让 vim 对该行进行智能缩进格式化,要么按需键入多次 < 或 > 手工缩进格式化;
  • softtabstop,如何处理连续多个空格。因为 expandtab 已经把制表符转换为空格,当你要删除制表符时你得连续删除多个空格,该设置就是告诉 vim 把连续数量的空格视为一个制表符,即,只删一个字符即可。通常应将这tabstop、shiftwidth、softtabstop 三个变量设置为相同值;
多层缩进 色块关联
  • cd ~/.vim/bundle && git clone git://github.com/nathanaelkane/vim-indent-guides.git
  • vim ~/.vimrc
    " 随 vim 自启动
    let g:indent_guides_enable_on_vim_startup=1
    " 从第二层开始可视化显示缩进
    let g:indent_guides_start_level=2
    " 色块宽度
    let g:indent_guides_guide_size=1
    " 快捷键 i 开/关缩进可视化
    :nmap <silent> <Leader>i <Plug>IndentGuidesToggle
  • 换行-空格-退格 解决断节处
代码折叠
  • vim ~/.vimrc
    " 基于缩进或语法进行代码折叠
    "set foldmethod=indent
    set foldmethod=syntax
    " 启动 vim 时关闭折叠代码
    set nofoldenable
  • za,打开或关闭当前折叠
  • zm,关闭所有折叠
  • zr,打开所有折叠
* 接口与实现快速切换
  • 习惯把类的接口和实现分在不同文件中,常会出现在接口文件(MyClass.h)和实现文件(MyClass.cpp)中来回切换的操作
  • cd ~/.vim/bundle && git clone https://github.com/vim-scripts/a.vim.git
  • vim ~/.vimrc
    " *.cpp 和 *.h 间切换
    nmap <Leader>ch :A<CR>
    " 子窗口中显示 *.cpp 或 *.h
    nmap <Leader>sch :AS<CR>
  • 键入 ;ch 就能在实现文件和接口文件间切换,键入 ;sch 子窗口中将显示实现文件/接口文件
  • a.vim 实现原理很简单,基于文件名进行关联,比如,a.vim 能识别 my_class.h 与 my_class.cpp,而无法识别 my_class.h 与 your_class.cpp。所以,你在命名文件时得注意下
* 代码收藏 书签可视化的插件vim-signature
  • mm 收藏的代码行 vim自带。可视化插件有很多快捷键,参考下面的链接
  • vim-signature(https://github.com/kshenoy/vim-signature)
  • cd ~/.vim/bundle && git clone https://github.com/kshenoy/vim-signature.git
  • vim 命令模式下键入
  • :echo has(‘signs’) 测试源码安装的 vim 是否具备 signs 特性
  • 若显示 1 则具备该特性,反之 0 则不具备该特性,重新编译vim
  • vim 的书签分为两类,独立书签和分类书签。独立书签,书签名只能由字母(a-zA-Z)组成,长度最多不超过 2 个字母,并且,同个文件中,不同独立书签名中不能含有相同字母,比如,a 和 bD 可以同时出现在同个文件在,而 Fc 和 c 则不行。分类书签,书签名只能由可打印特殊字符(!@#$%^&*())组成,长度只能有 1 个字符,同个文件中,你可以把不同行设置成同名书签,这样,这些行在逻辑上就归类成相同类型的书签了。
  • vim-signature 快捷键如下:
    let g:SignatureMap = {
            \ 'Leader'             :  "m",
            \ 'PlaceNextMark'      :  "m,",
            \ 'ToggleMarkAtLine'   :  "m.",
            \ 'PurgeMarksAtLine'   :  "m-",
            \ 'DeleteMark'         :  "dm",
            \ 'PurgeMarks'         :  "mda",
            \ 'PurgeMarkers'       :  "m<BS>",
            \ 'GotoNextLineAlpha'  :  "']",
            \ 'GotoPrevLineAlpha'  :  "'[",
            \ 'GotoNextSpotAlpha'  :  "`]",
            \ 'GotoPrevSpotAlpha'  :  "`[",
            \ 'GotoNextLineByPos'  :  "]'",
            \ 'GotoPrevLineByPos'  :  "['",
            \ 'GotoNextSpotByPos'  :  "mn",
            \ 'GotoPrevSpotByPos'  :  "mp",
            \ 'GotoNextMarker'     :  "[+",
            \ 'GotoPrevMarker'     :  "[-",
            \ 'GotoNextMarkerAny'  :  "]=",
            \ 'GotoPrevMarkerAny'  :  "[=",
            \ 'ListLocalMarks'     :  "ms",
            \ 'ListLocalMarkers'   :  "m?"
            \ }
  • 把上面的快捷键添加进~/.vimrc中
  • 常用的操作也就如下几类:
  • 书签设定。mx,设定/取消当前行名为 x 的标签;m,,自动设定下一个可用书签名,前面提说,独立书签名是不能重复的,在你已经有了多个独立书签,当想再设置书签时,需要记住已经设定的所有书签名,否则很可能会将已有的书签冲掉,这可不好,所以,vim-signature 为你提供了 m, 快捷键,自动帮你选定下一个可用独立书签名;mda,删除当前文件中所有独立书签。
  • 书签罗列。ms,罗列出当前文件中所有书签,选中后回车可直接跳转;
  • 书签跳转。mn,按行号前后顺序,跳转至下个独立书签;mp,按行号前后顺序,跳转至前个独立书签。书签跳转方式很多,除了这里说的行号前后顺序,还可以基于书签名字母顺序跳转、分类书签同类跳转、分类书签不同类间跳转等等。
  • vim-signature缺点是无法在不同文件的书签间跳转
* 代码导航
* 基于标签的导航
  • sudo apt-get install ctags
* 基于语义的导航
* 标签列表 tagbar 自动周期性调用 ctags 获取结果
* 内容查找 grep.vim、ack.vim、ctrlsf.vim显示上下文 这里设置得不是很好
  • sudo apt-get install ack-grep 在debian系中,ack这个名字被其他的软件占用了
  • sudo dpkg-divert –local –divert /usr/bin/ack –rename –add /usr/bin/ack-grep 重命名 ack-grep to ack
  • cd ~/.vim/bundle && git clone https://github.com/yegappan/grep.git && git clone https://github.com/mileszs/ack.vim.git
  • 此时在 Normal模式下 :Ack xxx * ,在项目里搜索xxx单词
  • vim ~/.vimrc && :map :Ack -i , -i参数表示忽略大小写. 以后在项目里,只需要按F4,即可全局搜索单词
  • 下面设置的是同时显示上下文
  • cd ~/.vim/bundle && git clone https://github.com/dyng/ctrlsf.vim.git
  • vim ~/.vimrc
> * " 使用 ctrlsf.vim 插件在工程内全局查找光标所在关键字,设置快捷键。快捷键速记法:search in project
> * nnoremap <Leader>sp :CtrlSF<CR>
  • 光标定位在该关键字上面,然后命令模式下键入
  • ;sp
内容替换
  • :[range]s/{pattern}/{string}/[flags]
  • 在进行内容替换操作时,我关注几个因素:如何指定替换文件范围、是否整词匹配、是否逐一确认后再替换
  • 如何指定替换文件范围?
  • 如果在当前文件内替换,[range] 不用指定,默认就在当前文件内;
  • 如果在当前选中区域,[range] 也不用指定,在你键入替换命令时,vim 自动将生成如下命令:
  • :’<,’>s/{pattern}/{string}/[flags]
  • 你也可以指定行范围,如,第三行到第五行:
  • :3,5s/{pattern}/{string}/[flags]
  • 如果对打开文件进行替换,你需要先通过 :bufdo 命令显式告知 vim 范围,再执行替换;
  • 如果对工程内所有文件进行替换,先 :args */.cpp /*.h 告知 vim 范围,再执行替换;
  • 是否整词匹配?{pattern} 用于指定匹配模式。如果需要整词匹配,则该字段应由 < 和 > 修饰待替换字符串(如,);无须整词匹配则不用修饰,直接给定该字符串即可;
  • 是否逐一确认后再替换?[flags] 可用于指定是否需要确认。若无须确认,该字段设定为 ge 即可;有时不见得所有匹配的字符串都需替换,若在每次替换前进行确认,该字段设定为 gec 即可。
  • 是否整词匹配和是否确认两个条件叠加就有 4 种组合:非整词且不确认、非整词且确认、整词且不确认、整词且确认,每次手工输入这些命令真是麻烦;我把这些组合封装到一个函数中,如下 Replace() 所示:
  • vim ~/.vimrc 添加下面两段话
    " 替换函数。参数说明:
    " confirm:是否替换前逐一确认
    " wholeword:是否整词匹配
    " replace:被替换字符串
    function! Replace(confirm, wholeword, replace)
        wa
        let flag = ''
        if a:confirm
            let flag .= 'gec'
        else
            let flag .= 'ge'
        endif
        let search = ''
        if a:wholeword
            let search .= '\<' . escape(expand('<cword>'), '/\.*$^~[') . '\>'
        else
            let search .= expand('<cword>')
        endif
        let replace = escape(a:replace, '/\&~')
        execute 'argdo %s/' . search . '/' . replace . '/' . flag . '| update'
    endfunction
  • 为最大程度减少手工输入,Replace() 还能自动提取待替换字符串(只要把光标移至待替换字符串上),同时,替换完成后自动为你保存更改的文件。现在要做的就是赋予 confirm、wholeword 不同实参实现 4 种组合,再绑定 4 个快捷键即可。如下:
    " 不确认、非整词
    nnoremap <Leader>R :call Replace(0, 0, input('Replace '.expand('<cword>').' with: '))<CR>
    " 不确认、整词
    nnoremap <Leader>rw :call Replace(0, 1, input('Replace '.expand('<cword>').' with: '))<CR>
    " 确认、非整词
    nnoremap <Leader>rc :call Replace(1, 0, input('Replace '.expand('<cword>').' with: '))<CR>
    " 确认、整词
    nnoremap <Leader>rcw :call Replace(1, 1, input('Replace '.expand('<cword>').' with: '))<CR>
    nnoremap <Leader>rwc :call Replace(1, 1, input('Replace '.expand('<cword>').' with: '))<CR>
  • 我平时用的最多的无须确认但整词匹配的替换模式,即 rw。
  • 我将工程的所有 .cpp 和 .h 中的关键字 MyClassA 按不确认且整词匹配模式替换成 MyClass,所以注释中的关键字不会被替换掉
  • 对当前文件采用需确认且无须整词匹配的模式进行替换,你会看到注释中的关键字也被替换了

代码开发

快速开关注释 NERD Commenter 这个有点慢
* 模板补全 UltiSnips
  • UltiSnips(https://github.com/SirVer/ultisnips
  • 新版 UltiSnips 并未自带预定义的代码模板,你可以从 https://github.com/honza/vim-snippets 获取各类语言丰富的代码模板,也可以重新写一套符合自己编码风格的模板。
  • 无论哪种方式,你需要在 .vimrc 中设定该模板所在目录名,以便 UltiSnips 寻找到。
  • 比如,我自定义的代码模板文件 cpp.snippets,路径为 ~/.vim/bundle/ultisnips/mysnippets/cpp.snippets,对应设置如下:
  • let g:UltiSnipsSnippetDirectories=[“mysnippets”] 其中,目录名切勿取为 snippets,这是 UltiSnips 内部保留关键字;
  • 另外,目录一定要是 ~/.vim/bundle/ 下的子目录,也就是 vim 的运行时目录。
  • 完整 cpp.snippets 内容如 见文首链接
  • 默认情况下,UltiSnips 模板补全快捷键是 ,与后面介绍的 YCM 快捷键有冲突,所有须在 .vimrc 中重新设定:
    " UltiSnips 的 tab 键与 YCM 冲突,重新设定
    let g:UltiSnipsExpandTrigger="<leader><tab>"
    let g:UltiSnipsJumpForwardTrigger="<leader><tab>"
    let g:UltiSnipsJumpBackwardTrigger="<leader><s-tab>"
* 智能补全 函数名和路径
* 基于标签的智能补全
* 基于语义的智能补全 YCM
* 由接口快速生成实现框架
  • .h 中写成员函数的声明,在 .cpp 中写成员函数的定义,很麻烦,我希望能根据函数声明自动生成函数定义的框架
* 库信息参考
  • 有过 win32 SDK 开发经验的朋友对 MSDN 或多或少有些迷恋吧,对于多达 7、8 个参数的 API,如果没有一套函数功能描述、参数讲解、返回值说明的文档,那么软件开发将是人间炼狱

工程管理

工程文件浏览 NERDtree
    " 使用 NERDTree 插件查看工程文件。设置快捷键,速记:file list
    nmap <Leader>fl :NERDTreeToggle<CR>
    " 设置NERDTree子窗口宽度
    let NERDTreeWinSize=32
    " 设置NERDTree子窗口位置
    let NERDTreeWinPos="right"
    " 显示隐藏文件
    let NERDTreeShowHidden=1
    " NERDTree 子窗口中不显示冗余帮助信息
    let NERDTreeMinimalUI=1
    " 删除文件时自动删除文件对应 buffer
    let NERDTreeAutoDeleteBuffer=1
  • :fl 显示右侧边栏
  • 回车,打开选中文件;
  • r,刷新工程目录文件列表;
  • I(大写),显示/隐藏隐藏文件;
  • m,出现创建/删除/剪切/拷贝操作列表。
  • 键入 fl 后,右边子窗口为工程项目文件列表
多文档编辑 MiniBufExplorer
    " 显示/隐藏 MiniBufExplorer 窗口
    map <Leader>bl :MBEToggle<cr>
    " buffer 切换快捷键
    map <C-Tab> :MBEbn<cr>
    map <C-S-Tab> :MBEbp<cr>
  • Ctrl + Tab 正向遍历 buffer
  • Ctrl + Shift + Tab 逆向遍历 (光标必须在 buffer 列表子窗口外)
  • 在某个 buffer 上键入 d 删除光标所在的 buffer(光标必须在 buffer 列表子窗口内)
  • 在某个 buffer 上键入 s 将该 buffer 对应 window 与先前 window 上下排列,键入 v 则左右排列(光标必须在 buffer 列表子窗口内)
  • 通过 vim 自身的 f 名字查找 buffer 序号可快速选择需要的 buffer
  • :bn 打开下一个buffer
  • :bp 打开上一个buffer
  • :b + num 打开第num个buffer
  • 另外,编辑单个文档时,不会出现 buffer 列表
环境恢复
  • vim 的编辑环境保存与恢复是我一直想要的功能,我希望每当重新打开 vim 时恢复:已打开文件、光标位置、undo/redo、书签、子窗口、窗口大小、窗口位置、命令历史、buffer 列表、代码折叠
  • vim 文档说借助 viminfo(恢复书签) 和 session(恢复除书签外的其他项)特性可以实现这个功能。请确保你的 vim 支持 +mksession 和 +viminfo 特性:
  • vim –version | grep mksession
  • vim –version | grep viminfo
  • 如果编译 vim 时添加了 –with-features=huge 选项那就没问题。
  • :wa 第一步,保存所有文档
  • 第二步,借助 viminfo 和 session 保存当前环境:
  • :mksession! my.vim
  • :wviminfo! my.viminfo
  • :qa 第三步,退出 vim
  • 第四步,恢复环境,进入 vim 后执行:
  • :source my.vim
  • :rviminfo my.viminfo
  • 具体能保存哪些项,可由 sessionoptions 指定,另外,前面几步可以设定快捷键
  • cd ~ && mkdir .undo_history/
  • vim ~/.vimrc
    " 设置环境保存项
    set sessionoptions="blank,buffers,globals,localoptions,tabpages,sesdir,folds,help,options,resize,winpos,winsize"
    " 保存折叠状态
    au BufWinLeave * silent mkview
    " 恢复折叠状态
    au BufRead * silent loadview
    " 保存 undo 历史
    set undodir=~/.undo_history/
    set undofile
    " 保存快捷键
    map <leader>ss :mksession! my.vim<cr> :wviminfo! my.viminfo<cr>
    " 恢复快捷键
    map <leader>rs :source my.vim<cr> :rviminfo my.viminfo<cr>
  • 这样,简化第二步、第四步操作。另外,sessionoptions 无法包含 undo 历史,所以,先得手工创建存放 undo 历史的目录(如,.undo_history/)再通过开启 undofile 进行单独设置,一旦开启,每次写文件时自动强制保存 undo 历史,下次加载在文件时自动强制恢复所有 undo 历史,不在由 :mksession/:wviminfo 和 :source/:rviminfo 控制
  • 按此操作,并不能像 vim 文档中描述的那样能保存所有环境,比如,书签、代码折叠、命令历史都无法恢复。这和我预期存在较大差距,暂且用用吧,找个时间再深入研究

工具链集成

编译器/构建工具集成
代码编译 LLVM/clang
  • 原文介绍的太繁琐,在新版中已经可以大大的简化了,请参见我的另一篇博客 LLVM/clang
系统构建 CMake
  • 一般来说,你需要先写个名为 CMakeLists.txt 的构建脚本,然后执行 cmake CMakeLists.txt 命令将生成 Makefile 文件,最后执行 make 命令即可编译生成可执行程序
  • 举例来说,你工程包含 main.cpp 文件,要构建它,你需要执行如下步骤
安装CMake
  • sudo apt-get insatll cmake 版本比较旧,可以换成新的
  • sudo apt-get autoremove cmake
  • cd /usr/local
  • wget https://cmake.org/files/v3.5/cmake-3.5.0-rc3.tar.gz 也可以去官网下载最新版本
  • tar zxvf cmake-3.5.0-rc3.tar.gz
  • ln -s /usr/local/cmake-3.5.0-rc3/bin/* /usr/bin/
  • cmake –version
第一步,编写 CMakeLists.txt
    PROJECT(main)
    SET(SRC_LIST main.cpp)
    SET(CMAKE_CXX_COMPILER "clang++")
    SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Werror -Weverything -Wno-deprecated-declarations -Wno-disabled-macro-expansion -Wno-float-equal -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-global-constructors -Wno-exit-time-destructors -Wno-missing-prototypes -Wno-padded -Wno-old-style-cast")
    SET(CMAKE_EXE_LINKER_FLAGS "-lc++ -lc++abi")
    SET(CMAKE_BUILD_TYPE Debug)
    ADD_EXECUTABLE(main ${SRC_LIST})
  • PROJECT 指定工程名、SET 是 cmake 变量赋值命令、ADD_EXECUTABLE 指定生成可执行程序的名字。括号内的大写字符串是 cmake 内部预定义变量,这是 CMakeLists.txt 脚本的重点,下面详细讲述
  • SRC_LIST 指定参与编译的源码文件列表,如果有多个文件请用空格隔开,如,你工程有 main.cpp、lib/MyClass.cpp、lib/MyClass.h 三个文件,那么可以指定为:SET(SRC_LIST main.cpp lib/MyClass.cpp)
  • CMAKE_CXX_COMPILER 指定选用何种编译器;
  • CMAKE_CXX_FLAGS 设定编译选项;
  • CMAKE_EXE_LINKER_FLAGS 设定链接选项。一定要将 -lc++ 和 -lc++abi 独立设定到 CMAKE_EXE_LINKER_FLAGS 变量中而不能放在 CMAKE_CXX_FLAGS,否则无法通过链接;
  • CMAKE_BUILD_TYPE 设定生成的可执行程序中是否包含调试信息
  • 另外,对于编译选项,我的原则是严己宽人。也就是说,在我本机上使用最严格的编译选项以发现尽量多 bug,发布给其他人的源码包使用最宽松的编译选项以减少环境差异导致编译失败的可能。前面罗列出来的就是严格版的 CMakeLists.txt,宽松版我会考虑:编译器改用 GCC(很多人没装 clang)、忽略所有编译警告、让编译器进行代码优化、去掉调试信息、添加安装路径等要素,具体如下
    PROJECT(main)
    SET(SRC_LIST main.cpp)
    SET(CMAKE_CXX_COMPILER "g++")
    SET(CMAKE_CXX_FLAGS "-std=c++11 -O3")
    SET(CMAKE_BUILD_TYPE Release)
    ADD_EXECUTABLE(porgram_name ${SRC_LIST})
    INSTALL(PROGRAMS porgram_name DESTINATION /usr/bin/)
第二步,基于 CMakeLists.txt 生成 Makefile
  • cmake CMakeLists.txt 在该目录下看到 Makefile 文件
第三步,基于 Makefile 生成可执行程序。相同目录下执行
  • make
  • 这一步,就是在调用编译器进行编译,如果存在代码问题,修正错误后重新执行这一步即可,不用再次执行第一、二步。
  • 基本上,你的新工程,可以在基于上面的 CMakeLists.txt 进行修改,执行一次第二步后,每次代码调整只需执行第三步即可
一键编译
  • 第一步的创建 CMakeLists.txt 没问题,vim 这么优秀的编辑器编辑个普通文本文件易如反掌;
  • 第二步的生成 Makefile 也没问题,在 vim 内部通过 ! 前缀可以执行 shell 命令,:!cmake CMakeLists.txt 即可;
  • 第三步的编译过程更没问题,因为 vim 自身支持 make 命令,直接在 vim 中输入 :make 命令它会调用外部 make 程序读取当前目录中的 Makefile 文件,完成编译、链接操作。
  • 当然,一次性编译通过的可能性很小,难免有些语法错误(语义错误只能靠调试器了),vim 将编译器抛出的错误和警告信息输出到 quickfix 中,执行 :cw 命令即可显示 quickfix。
  • 说了这么多,概要之,先通过构建工具(CMake 可通过 CMakeLists.txt 文件,autotools 可通过 configure 文件)生成整个工程的 Makefile,再在 vim 中执行 :make,最后显示 quickfix
  • vim ~/.vimrc
    nmap <Leader>m :wa<CR>:make<CR><CR>:cw<CR>
  • m 为设定的一键编译快捷键,:wa 保存所有调整文档内容,
  • :make 调用 make 命令,后面的 消除执行完 make 命令屏幕上“Press ENTER or type command to continue”的输入等待提示,
  • :cw 显示 quickfix(仅当有编译错误或警告时)
  • 上面那个可能会遇到错误,具体见Github博客,换成下面这句话
    nmap <Leader>m :!rm -rf main<CR>:wa<CR>:make<CR><CR>:cw<CR>
  • 最后,再次强调实现一键编译及运行的几个前提:vim 的当前目录必须为工程目录、事前准备好 Makefile 文件且放于工程目录的根目录、生成的程序必须在工程目录的根目录
一键编译及运行
  • 到此,已实现一键编译,要实现一键编译及运行无非就在刚才的快捷键中追加绑定运行程序的外部命令即可。新快捷键设定为 g,假定生成的可执行程序名为 main,将如下配置信息加入 .vimrc 中
    nmap <Leader>g :!rm -rf main<CR>:wa<CR>:make<CR>:cw<CR><CR>:!./main<CR>
  • 注意要自己写CMakeLists.txt和执行一次!cmake CMakeList.txt,然后执行;m ;g
* 静态分析器集成 syntastic

其他辅助

* 快速编辑结对符 UltiSnips wildfire.vim
  • 要高效输入结对符,应该是输入少量几个字母(对,字母,不是字符)后 vim 自动为你输入完整结对符,而非是我输入一半 vim 输入另一半(不用 delimitMate 的原因)
* 支持分支的undo gundo.vim
快速移动 easymotion
* markdown即时预览 Markdown Viewer vim-instant-markdown
中/英输入平滑切换 fcitx.vim
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值