在Visual Studio编译gvim和ycmd

目录
[隐藏]

引言:考虑到似乎有不少人参考本文,说明下缘由。之前我一直都是在Cygwin的minty里面使用vim的,llvm/clang是官网的源的,这和Ubuntu、Mac等一样,系统官方源里面自带的llvm/clang一般来说是比自己编译的llvm要方便得多的。对Cygwin的继承者msys2一样的道理。然而Cygwin/msys2看起来编译很爽,如果提前从官方源里面安装好了各种依赖,安装ycmd基本上一键安装,自动编译完成,确实挺方便的。

然而Cygwin对Linux的模拟是有代价的,一般在minty里面vim a.cpp至少要10秒以上才能启动,基本上就是摆设,我大约都是用nano来简单编辑配置,而用alias subl=”/path/to/subl.exe $1″调用sublime来编辑程序文件。sublime的速度真的没话说,比那些atom系列的编辑器都要快(装了大几十个插件后带插件启动1秒钟内启动)。

而编译vim起初目的只是好玩,而事实也证明Visual studio编译的gvim对windows的兼容性与性能都远远好于Cygwin下面的。

总的来说在Windows平台Visual Studio毕竟是原生的编译器,可以直接调用的Windows API要多于stdc++等库带bug地模拟Linux的效果。而且路劲问题就需要用技巧来解决(我确实有一个几乎完美的解决方案),得不偿失。

下午6点钟真不是个写东西的好时候,简要地贴点关键编译命令,然后以后来整理吧。

本文编译的gvim,原生Windows x64的GUI支持,基本上可以使用全部的k-vim配置,包括最难支持的ycmd的C family支持。

本文需要:

VS2013,

cmake(下载最新稳定版,安装到默认目录即可),

Subversion(svn.exe在path,cygwin的不行),

mercurial(hg.exe在path),

git(git.exe/git.cmd在path,用于支持Vundle,具体参考这里的要求),

curl(要求curl.exe在path,同git的理由),

系统需要是64位的。

(补充下,实际cygwin的bin在path即可,然而cygwin的bin会导致一些其他的问题,会让一些开源软件的脚本认为自己在Linux/MingW/Cygwin上运行,但是cygwin的mercurial则肯定不行)

先来两张图吧。

c++头文件补全

c++头文件补全


库函数补全

库函数补全


C++补全

C++补全

c++提示

c++提示

中文显示

中文显示

目录补全

目录补全

1.编译gvim

1.1获取源码,准备编译脚本

首先得下载到vim的源码,官网下载方式在这里.

hg clone https://vim.googlecode.com/hg/ vim

更新代码可以用

cd vim
hg pull
hg update

当然也发现了这里一个github的镜像只读repo。

编译参考了这里。具体来说,我使用的脚本如下:

@echo off
cd /d %~dp0\vim\src
SET TOOLDIR=E:\vim_tools
SET INCLUDE=%TOOLDIR%\ruby222-x64\include\ruby-2.2.0\x64-mswin64_120;%TOOLDIR%\ruby222-x64\include\ruby-2.2.0;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include
rem start "Vim build" 
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
echo "Begin to build..."
pause
nmake -f Make_mvc.mak CPU=AMD64 GUI=yes OLE=yes CSCOPE=yes FEATURES=HUGE MBYTE=yes ARABIC=no FARSI=no NETBEANS=yes IME=yes GIME=yes SNIFF=yes DIRECTX=yes PYTHON=C:\python27 DYNAMIC_PYTHON=yes PYTHON_VER=27 PYTHON3=C:\Python34 DYNAMIC_PYTHON3=yes PYTHON3_VER=34 PERL=%TOOLDIR%\Perl64 DYNAMIC_PERL=yes PERL_VER=520 LUA=%TOOLDIR%\lua-5.3_Win64_vc12_lib LUA_VER=53 DYNAMIC_LUA=no TCL=%TOOLDIR%\Tcl TCL_VER=86 TCL_VER_LONG=8.6 DYNAMIC_TCL=yes RUBY=%TOOLDIR%\ruby222-x64 DYNAMIC_RUBY=yes RUBY_VER=22 RUBY_VER_LONG=2.2.2 RUBY_INSTALL_NAME=x64-msvcr120-ruby220 RUBY_PLATFORM=x64-mswin64_120
IF ERRORLEVEL 1 goto ERROR
IF ERRORLEVEL 0 goto QUIT
:ERROR
echo Error!
pause
:QUIT
rem exit

上面的脚本保存为_build_vim.bat,放在vim源码所在上一级目录。

从上面的代码可以看到我们需要ruby,python2,python3,lua,perl,tcl等。所以现在只是保存这个脚本,还不能运行它。下面要开始装依赖,然而依赖我是全部装到了E:\vim_tools下面,如果你不是这个目录,那么对应修改上面的SET TOOLDIR=E:\vim_tools即可。

接着一个脚本用来拷贝编译生成的文件到单独的目录。

@echo off
set SRC=%~dp0\vim
set DST=%~dp0\vim74
if not exist %DST% md %DST%
xcopy %SRC%\runtime %DST% /D /E /H /I /Y %*
xcopy %SRC%\src\xxd\xxd.exe %DST%\* /D /Y %*
xcopy %SRC%\src\GvimExt\gvimext.dll %DST%\* /D /Y %*
xcopy %SRC%\src\*.exe %DST%\* /D /Y %*
IF ERRORLEVEL 1 goto ERROR
IF ERRORLEVEL 0 goto QUIT
:ERROR
echo Error!
pause
:QUIT
rem exit

其中set DST=%~dp0\vim74一行是你将来用来放“成果”的地方,你可以改成你的目标地址,如果按照本文方式,现在需要把上面的批处理存为_copy_vim.bat,然后新建一个目录vim74.

到目前为止工作目录看起来应该是这样的,其中vim是hg clone下来的源码。

vim

vim74

_copy_vim.bat

_build_vim.bat

1.2安装依赖

本文是打算编译64位的版本,因为ycmd貌似需要64位才工作(? 我印象是这样,没有确认)。所以下载的的依赖全部是64位的。

具体来说如下列表的需要下载:

python-2.7.10.amd64.msi与python-3.4.2.msi 在这个页面下载。你可以下载python2 x64的最新版,因为你看到本文的时候很可能python2 x64已经升级了。注意安装的目录需要是C:\Python27与 C:\Python34,如果不是你需要自己修改_build_vim.bat

ActivePerl-5.20.2.2001-MSWin32-x86-64int-298913.msi 在这个页面下载。可以保持最新版本,只要是最新的windows x64即可。注意安装目录需要是E:\vim_tools\Perl64,如果不是E:\vim_tools下面,需要修改_build_vim.bat里面的SET TOOLDIR=E:\vim_tools

ActiveTcl8.6.4.0.298892-win32-x86_64-threaded.exe 在这个页面下载,可以保持最新的windows x64版本。注意安装目录需要是E:\vim_tools\Tcl,如果不是E:\vim_tools下面,需要修改_build_vim.bat里面的SET TOOLDIR=E:\vim_tools

lua-5.3_Win64_vc12_lib.zip 下载页面是这里,然而主页在这里。注意解压的目录是E:\vim_tools\lua-5.3_Win64_vc12_lib,如果不是E:\vim_tools下面,需要修改_build_vim.bat里面的SET TOOLDIR=E:\vim_tools

1.3编译ruby2.2.2

还差个ruby,虽然ruby官网推荐的是railsinstaller,我写本文的时候最新版本是railsinstaller-3.1.0.exe,里面是ruby2.2.0,重点是它是ruby mingw的,基本上与本文标题说的Visual Studio编译没法成功了。然而ruby的源码对Visual Studio工具链相当友好。ruby是我发现并且自己编译的第一个Opensouce项目,用Visual Studio工具链编译,而且有test,nmake test全部通过的。这是非常罕见的。当然Python,node可能早就是这样了,但是node,Python官网是出msi安装文件的。

ruby-2.2.2.tar.gz 在这个页面下载,下载Source code的Current stable即可。解压到E:\vim_tools\ruby-2.2.2,然后在E:\vim_tools新建_build_ruby.bat,内容如下

@echo off
cd /d %~dp0\ruby-2.2.2
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
win32\configure.bat --prefix="%~dp0\ruby222-x64" --target=x64-mswin64
nmake
nmake test
nmake install
IF ERRORLEVEL 1 goto ERROR
IF ERRORLEVEL 0 goto QUIT
:ERROR
echo Error!
pause
:QUIT
rem exit

开始编译ruby。

非常简单,点击_build_ruby.bat,等待运行结束即可。然后你会发现ruby222-x64多了出来这就是我们要的ruby222编译成功了。

如果要支持64位Racket/MaScheme,请参考Visual Studio编译gvim支持Racket(mzscheme)

1.4编译gvim

运行前面的_build_vim.bat,然后运行_copy_vim.bat。那么我们的gvim编译成功了。你可以打开vim74下面的gvim.exe看看。关于配置后面专门一篇来讲。我主要就是用k-vim的配置。

如果要更新vim到最新的源码,需要运行

cd vim
hg pull
hg update

然而我们还需要一个脚本来再次编译,下面的代码会清除vim目录编译生成的exe,dll等,这样再次_build_vim.bat就是重新编译的版本。把下面代码保存到_build_vim.bat所在目录,文件名为_clean_vim.bat

@echo off
cd /d %~dp0\vim\src
rem start "Vim build" 
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
echo "Begin to clean..."
pause
nmake -f Make_mvc.mak clean
IF ERRORLEVEL 1 goto ERROR
IF ERRORLEVEL 0 goto QUIT
:ERROR
echo Error!
pause
:QUIT

2.配置vim

2.1启动脚本与右键菜单配置

前面安装和编译的那些语言,现在gvim.exe还是找不到的,我们不需要修改我们的系统PATH。

现在vim74目录复制到哪里都是可以运行的,假设我们就是放在E:\vim74目录下。

那么我们进入vim74目录,新建一个批处理gvim.bat(文件名不能改),内容如下:

@echo off

SET TOOLDIR=E:\vim_tools

SET PERL_PATH=%TOOLDIR%\Perl64
SET TCL_PATH=%TOOLDIR%\Tcl
SET LUA_PATH=%TOOLDIR%\lua-5.3_Win64_vc12_lib
SET RUBY_PATH=%TOOLDIR%\ruby222-x64
SET LLVM_PATH=%TOOLDIR%\llvim3.7.0

SET PATH=%TCL_PATH%\bin;%PERL_PATH%\bin;%RUBY_PATH%\bin;%LUA_PATH%;%LLVM_PATH%\bin;C:\Python27;C:\Python34;%path%

SET HOME=E:\vim-home
SET TEMP=%HOME%\tmp
SET TMP=%HOME%\tmp
START %~dp0\gvim.exe %*

然后把gvim添加到注册表,同样在在vim74目录新建,一个“系统鼠标右键菜单.bat”的文件,不包括引号。内容如下:

@echo Off
:START
CLS
echo *=========================================================================*
echo *                                                                         *
echo *                            [A]添加右键菜单                              *
echo *                            [D]删除右键菜单                              *
echo *                            [Q]退出                                      *
echo *                                                                         *
echo *=========================================================================*
Set /P Choice=       请选择要进行的操作 (A/D/Q) ,然后按回车:
If /I "%Choice%"=="A" Goto :ADD
If /I "%Choice%"=="D" Goto :DEL
If /I "%Choice%"=="Q" Exit
 
START
 
:ADD
CLS
echo Windows Registry Editor Version 5.00> tmp.reg 
echo [HKEY_CLASSES_ROOT\*\shell]>> tmp.reg 
echo [HKEY_CLASSES_ROOT\*\shell\gVim]>> tmp.reg 
echo @="gVim">> tmp.reg 
echo [HKEY_CLASSES_ROOT\*\shell\gVim\Command]>> tmp.reg 
rem set str=%cd%
rem changed by rexdf 7/14/2014
set str=%~dp0%
echo @="\"%str:\=\\%gvim.bat\" -p --remote-tab-silent \"%%1\"\"%%*\"">> tmp.reg 
echo *=========================================================================*
echo *                                                                         *
echo *   正在将生成的注册信息写入注册表,请点击“是”键钮!                      *
echo *                                                                         *
echo *=========================================================================*
tmp.reg
del tmp.reg
GOTO :START
 
:DEL
echo Windows Registry Editor Version 5.00> tmp.reg 
echo [-HKEY_CLASSES_ROOT\*\shell\gVim]>> tmp.reg 
tmp.reg
del tmp.reg
GOTO :START

右键管理员运行,输入A,添加。那么你现在任何文件上面右键都会发现一个gVim的选项了。如果要删除右键菜单,再次管理员运行,输入d即可。完全绿色安装卸载,不像大部分国产软件。

2.2vim的配置

我主要就是用k-vim的配置。然而gvim还需要定制下。

注意上面的gvim.bat里面有一行SET HOME=E:\vim-home,这是一个关键的欺骗。而且VIM能够良好地接受这个欺骗。简单点说,如果不设置这一行,那么配置文件会放到C:\Users\你的用户名\,这个目录杂的很,基本上如果可能我都会设置软件避开使用这个目录。

现在我们需要建立E:\vim-home目录,首先建立一个tmp目录用来保存一些临时信息,然后在这个目录新建如下三个文件(注意前两个是无后缀文件):

_vimrc

"==========================================
" Author:  wklken
" Version: 8.1
" Email: wklken@yeah.net
" BlogPost: http://www.wklken.me
" ReadMe: README.md
" Donation: http://www.wklken.me/pages/donation.html
" Last_modify: 2015-05-02
" Sections:
"       -> Initial Plugin 加载插件
"       -> General Settings 基础设置
"       -> Display Settings 展示/排版等界面格式设置
"       -> FileEncode Settings 文件编码设置
"       -> Others 其它配置
"       -> HotKey Settings  自定义快捷键
"       -> FileType Settings  针对文件类型的设置
"       -> Theme Settings  主题设置
"
"       -> 插件配置和具体设置在vimrc.bundles中
"==========================================

"==========================================
" Initial Plugin 加载插件
"==========================================
set encoding=utf-8
set helplang=cn
language chinese_china 
set langmenu=zh_CN
set langmenu=zh_CN.UTF-8

" 修改leader键
let mapleader = ','
let g:mapleader = ','

" 开启语法高亮
syntax on

" install Vundle bundles
if filereadable(expand("~/vimrc.bundles"))
  source ~/vimrc.bundles
endif
" ensure ftdetect et al work by including this after the Vundle stuff
filetype plugin indent on

"==========================================
" General Settings 基础设置
"==========================================

"以下配置有详细说明,一些特性不喜欢可以直接注解掉

"set guifont=Monaco:h20          " 字体 && 字号

" history存储容量
set history=2000

"检测文件类型
filetype on
"针对不同的文件类型采用不同的缩进格式
filetype indent on
"允许插件
filetype plugin on
"启动自动补全
filetype plugin indent on

set autoread          " 文件修改之后自动载入。
set shortmess=atI       " 启动的时候不显示那个援助索马里儿童的提示

" 备份,到另一个位置. 防止误删, 目前是取消备份
"set backup
"set backupext=.bak
"set backupdir=/tmp/vimbk/

" 取消备份。 视情况自己改
set nobackup
" 关闭交换文件
set noswapfile

"create undo file
if has('persistent_undo')
  set undolevels=1000         " How many undos
  set undoreload=10000        " number of lines to save for undo
  set undofile                " So is persistent undo ...
  set undodir=~/tmp
endif

set wildignore=*.swp,*.bak,*.pyc,*.class,.svn
" 突出显示当前行等
"set cursorcolumn
set cursorline          " 突出显示当前行


"设置 退出vim后,内容显示在终端屏幕, 可以用于查看和复制
"好处:误删什么的,如果以前屏幕打开,可以找回
set t_ti= t_te=


"- 则点击光标不会换,用于复制
"set mouse-=a             " 鼠标暂不启用, 键盘党....
" set mouse=a                 " Automatically enable mouse usage
set mousehide               " Hide the mouse cursor while typing


" 修复ctrl+m 多光标操作选择的bug,但是改变了ctrl+v进行字符选中时将包含光标下的字符
"set selection=exclusive
set selection=inclusive
set selectmode=mouse,key

" No annoying sound on errors
" 去掉输入错误的提示声音
"set title                " change the terminal's title
"set novisualbell         " don't beep
"set noerrorbells         " don't beep
"set t_vb=
set tm=500

" Remember info about open buffers on close"
set viminfo^=%

" For regular expressions turn magic on
set magic

" Configure backspace so it acts as it should act
set backspace=eol,start,indent
set whichwrap+=<,>,h,l

"==========================================
" Display Settings 展示/排版等界面格式设置
"==========================================
"
"显示当前的行号列号:
set ruler
""在状态栏显示正在输入的命令
set showcmd
" 左下角显示当前vim模式
set showmode

" 在上下移动光标时,光标的上方或下方至少会保留显示的行数
set scrolloff=7

" set winwidth=79

" 命令行(在状态行下)的高度,默认为1,这里是2
set statusline=%<%f\ %h%m%r%=%k[%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}]\ %-14.(%l,%c%V%)\ %P
" Always show the status line - use 2 lines for the status bar
set laststatus=2

"显示行号:
set number
" 取消换行。
"set nowrap

" 括号配对情况,跳转并高亮一下匹配的括号
set showmatch
" How many tenths of a second to blink when matching brackets
set matchtime=2

"设置文内智能搜索提示
" 高亮search命中的文本。
set hlsearch
" 打开增量搜索模式,随着键入即时搜索
set incsearch
" 搜索时忽略大小写
set ignorecase
" 有一个或以上大写字母时仍大小写敏感
set smartcase     " ignore case if search pattern is all lowercase, case-sensitive otherwise

" 代码折叠
set foldenable
" 折叠方法
" manual    手工折叠
" indent    使用缩进表示折叠
" expr      使用表达式定义折叠
" syntax    使用语法定义折叠
" diff      对没有更改的文本进行折叠
" marker    使用标记进行折叠, 默认标记是 {{{ 和 }}}
set foldmethod=indent
set foldlevel=99
" 代码折叠自定义快捷键
let g:FoldMethod = 0
map <leader>zz :call ToggleFold()<cr>
fun! ToggleFold()
    if g:FoldMethod == 0
        exe "normal! zM"
        let g:FoldMethod = 1
    else
        exe "normal! zR"
        let g:FoldMethod = 0
    endif
endfun

" 缩进配置

set smartindent   " Smart indent
set autoindent    " 打开自动缩进
" never add copyindent, case error   " copy the previous indentation on autoindenting

" tab相关变更
set tabstop=4     " 设置Tab键的宽度        [等同的空格个数]
set shiftwidth=4  " 每一次缩进对应的空格数
set softtabstop=4 " 按退格键时可以一次删掉 4 个空格
set smarttab      " insert tabs on the start of a line according to shiftwidth, not tabstop 按退格键时可以一次删掉 4 个空格
set expandtab     " 将Tab自动转化成空格    [需要输入真正的Tab键时,使用 Ctrl+V + Tab]
set shiftround    " 缩进时,取整 use multiple of shiftwidth when indenting with '<' and '>'

" A buffer becomes hidden when it is abandoned
set hidden
set wildmode=list:longest
set ttyfast

" 00x增减数字时使用十进制
set nrformats=


" 相对行号      行号变成相对,可以用 nj  nk   进行跳转 5j   5k 上下跳5行
set relativenumber number
au FocusLost * :set norelativenumber number
au FocusGained * :set relativenumber
" 插入模式下用绝对行号, 普通模式下用相对
autocmd InsertEnter * :set norelativenumber number
autocmd InsertLeave * :set relativenumber
function! NumberToggle()
  if(&relativenumber == 1)
    set norelativenumber number
  else
    set relativenumber
  endif
endfunc
nnoremap <C-n> :call NumberToggle()<cr>


"==========================================
" FileEncode Settings 文件编码,格式
"==========================================
" 设置新文件的编码为 UTF-8
set encoding=utf-8
" 自动判断编码时,依次尝试以下编码:
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
"set helplang=cn
"set langmenu=zh_CN.UTF-8
"set enc=2byte-gb18030
" 下面这句只影响普通模式 (非图形界面) 下的 Vim。
set termencoding=utf-8

" Use Unix as the standard file type
set ffs=unix,dos,mac

" 如遇Unicode值大于255的文本,不必等到空格再折行。
set formatoptions+=m
" 合并两行中文时,不在中间加空格:
set formatoptions+=B


"==========================================
" others 其它设置
"==========================================
autocmd! bufwritepost _vimrc source % " vimrc文件修改之后自动加载。 windows。
autocmd! bufwritepost _gvimrc source % 
autocmd! bufwritepost .vimrc source % " vimrc文件修改之后自动加载。 linux。

" 自动补全配置
"让Vim的补全菜单行为与一般IDE一致(参考VimTip1228)
set completeopt=longest,menu

" 增强模式中的命令行自动完成操作
set wildmenu
" Ignore compiled files
set wildignore=*.o,*~,*.pyc,*.class

"离开插入模式后自动关闭预览窗口
autocmd InsertLeave * if pumvisible() == 0|pclose|endif
"回车即选中当前项
inoremap <expr> <CR>       pumvisible() ? "\<C-y>" : "\<CR>"

"上下左右键的行为 会显示其他信息
inoremap <expr> <Down>     pumvisible() ? "\<C-n>" : "\<Down>"
inoremap <expr> <Up>       pumvisible() ? "\<C-p>" : "\<Up>"
inoremap <expr> <PageDown> pumvisible() ? "\<PageDown>\<C-p>\<C-n>" : "\<PageDown>"
inoremap <expr> <PageUp>   pumvisible() ? "\<PageUp>\<C-p>\<C-n>" : "\<PageUp>"

" if this not work ,make sure .viminfo is writable for you
if has("autocmd")
  au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
endif

"==========================================
" HotKey Settings  自定义快捷键设置
"==========================================

" 主要按键重定义

" 关闭方向键, 强迫自己用 hjkl
"map <Left> <Nop>
"map <Right> <Nop>
"map <Up> <Nop>
"map <Down> <Nop>

"Treat long lines as break lines (useful when moving around in them)
"se swap之后,同物理行上线直接跳
nnoremap k gk
nnoremap gk k
nnoremap j gj
nnoremap gj j

" F1 - F6 设置
" F1 废弃这个键,防止调出系统帮助
" F2 行号开关,用于鼠标复制代码用
" F3 显示可打印字符开关
" F4 换行开关
" F5 粘贴模式paste_mode开关,用于有格式的代码粘贴
" F6 语法开关,关闭语法可以加快大文件的展示

" I can type :help on my own, thanks.  Protect your fat fingers from the evils of <F1>
"noremap <F1> <Esc>"

""为方便复制,用<F2>开启/关闭行号显示:
function! HideNumber()
  if(&relativenumber == &number)
    set relativenumber! number!
  elseif(&number)
    set number!
  else
    set relativenumber!
  endif
  set number?
endfunc
nnoremap <F2> :call HideNumber()<CR>
nnoremap <F3> :set list! list?<CR>
nnoremap <F4> :set wrap! wrap?<CR>
              "set paste
set pastetoggle=<F5>            "    when in insert mode, press <F5> to go to
                                "    paste mode, where you can paste mass data
                                "    that won't be autoindented

" disbale paste mode when leaving insert mode
au InsertLeave * set nopaste

nnoremap <F6> :exec exists('syntax_on') ? 'syn off' : 'syn on'<CR>


"Smart way to move between windows 分屏窗口移动
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

" Go to home and end using capitalized directions
noremap H ^
noremap L $


"Map ; to : and save a million keystrokes
" ex mode commands made easy 用于快速进入命令行
nnoremap ; :


" 命令行模式增强,ctrl - a到行首, -e 到行尾
cnoremap <C-j> <t_kd>
cnoremap <C-k> <t_ku>
cnoremap <C-a> <Home>
cnoremap <C-e> <End>

" 搜索相关

" Map <Space> to / (search) and Ctrl-<Space> to ? (backwards search)
map <space> /
" 进入搜索Use sane regexes"
nnoremap / /\v
vnoremap / /\v

"Keep search pattern at the center of the screen."
nnoremap <silent> n nzz
nnoremap <silent> N Nzz
nnoremap <silent> * *zz
nnoremap <silent> # #zz
nnoremap <silent> g* g*zz

" switch # *
nnoremap # *
nnoremap * #

" for # indent, python文件中输入新行时#号注释不切回行首
autocmd BufNewFile,BufRead *.py inoremap # X<c-h>#


" 去掉搜索高亮
noremap <silent><leader>/ :nohls<CR>

" --------tab/buffer相关

"Use arrow key to change buffer"
" TODO: 如何跳转到确定的buffer?
" :b1 :b2   :bf :bl
nnoremap [b :bprevious<cr>
nnoremap ]b :bnext<cr>
noremap <left> :bp<CR>
noremap <right> :bn<CR>


" tab 操作
" TODO: ctrl + n 变成切换tab的方法
" http://vim.wikia.com/wiki/Alternative_tab_navigation
" http://stackoverflow.com/questions/2005214/switching-to-a-particular-tab-in-vim
"map <C-2> 2gt
map <leader>th :tabfirst<cr>
map <leader>tl :tablast<cr>

map <leader>tj :tabnext<cr>
map <leader>tk :tabprev<cr>
map <leader>tn :tabnext<cr>
map <leader>tp :tabprev<cr>

map <leader>te :tabedit<cr>
map <leader>td :tabclose<cr>
map <leader>tm :tabm<cr>


" 新建tab  Ctrl+t
nnoremap <C-t>     :tabnew<CR>
inoremap <C-t>     <Esc>:tabnew<CR>
" TODO: 配置成功这里, 切换更方便, 两个键
" nnoremap <C-S-tab> :tabprevious<CR>
" nnoremap <C-tab>   :tabnext<CR>
" inoremap <C-S-tab> <Esc>:tabprevious<CR>i
" inoremap <C-tab>   <Esc>:tabnext<CR>i
" nnoremap <C-Left> :tabprevious<CR>
" nnoremap <C-Right> :tabnext<CR>

" normal模式下切换到确切的tab
noremap <leader>1 1gt
noremap <leader>2 2gt
noremap <leader>3 3gt
noremap <leader>4 4gt
noremap <leader>5 5gt
noremap <leader>6 6gt
noremap <leader>7 7gt
noremap <leader>8 8gt
noremap <leader>9 9gt
noremap <leader>0 :tablast<cr>

" Toggles between the active and last active tab "
" The first tab is always 1 "
let g:last_active_tab = 1
" nnoremap <leader>gt :execute 'tabnext ' . g:last_active_tab<cr>
" nnoremap <silent> <c-o> :execute 'tabnext ' . g:last_active_tab<cr>
" vnoremap <silent> <c-o> :execute 'tabnext ' . g:last_active_tab<cr>
nnoremap <silent> <leader>tt :execute 'tabnext ' . g:last_active_tab<cr>
vnoremap <silent> <leader>tt :execute 'tabnext ' . g:last_active_tab<cr>
autocmd TabLeave * let g:last_active_tab = tabpagenr()


" ------- 选中及操作改键

"Reselect visual block after indent/outdent.调整缩进后自动选中,方便再次操作
vnoremap < <gv vnoremap > >gv

" y$ -> Y Make Y behave like other capitals
map Y y$

" select all
map <Leader>sa ggVG"

" select block
nnoremap <leader>v V`}

" w!! to sudo & write a file
cmap w!! w !sudo tee >/dev/null %

" kj 替换 Esc
inoremap kj <Esc>

" 滚动Speed up scrolling of the viewport slightly
nnoremap <C-e> 2<C-e>
nnoremap <C-y> 2<C-y>


"Jump to start and end of line using the home row keys
" 增强tab操作, 导致这个会有问题, 考虑换键
"nmap t o<ESC>k
"nmap T O<ESC>j

" Quickly close the current window
nnoremap <leader>q :q<CR>

" Swap implementations of ` and ' jump to markers
" By default, ' jumps to the marked line, ` jumps to the marked line and
" column, so swap them
nnoremap ' `
nnoremap ` '

" remap U to <C-r> for easier redo
nnoremap U <C-r>

" Quickly edit/reload the vimrc file
nmap <silent> <leader>ev :e $MYVIMRC<CR>
nmap <silent> <leader>sv :so $MYVIMRC<CR>

"==========================================
" FileType Settings  文件类型设置
"==========================================

" Python 文件的一般设置,比如不要 tab 等
autocmd FileType python set tabstop=4 shiftwidth=4 expandtab ai
autocmd FileType ruby set tabstop=2 shiftwidth=2 softtabstop=2 expandtab ai
autocmd BufRead,BufNew *.md,*.mkd,*.markdown  set filetype=markdown.mkd


" 保存python文件时删除多余空格
fun! <SID>StripTrailingWhitespaces()
    let l = line(".")
    let c = col(".")
    %s/\s\+$//e
    call cursor(l, c)
endfun
autocmd FileType c,cpp,java,go,php,javascript,puppet,python,rust,twig,xml,yml,perl autocmd BufWritePre <buffer> :call <SID>StripTrailingWhitespaces()


" 定义函数AutoSetFileHead,自动插入文件头
autocmd BufNewFile *.sh,*.py exec ":call AutoSetFileHead()"
function! AutoSetFileHead()
    "如果文件类型为.sh文件
    if &filetype == 'sh'
        call setline(1, "\#!/bin/bash")
    endif

    "如果文件类型为python
    if &filetype == 'python'
        call setline(1, "\#!/usr/bin/env python")
        call append(1, "\# encoding: utf-8")
    endif

    normal G
    normal o
    normal o
endfunc


" set some keyword to highlight
if has("autocmd")
  " Highlight TODO, FIXME, NOTE, etc.
  if v:version > 701
    autocmd Syntax * call matchadd('Todo',  '\W\zs\(TODO\|FIXME\|CHANGED\|DONE\|XXX\|BUG\|HACK\)')
    autocmd Syntax * call matchadd('Debug', '\W\zs\(NOTE\|INFO\|IDEA\|NOTICE\)')
  endif
endif

"==========================================
" Theme Settings  主题设置
"==========================================

" theme主题
"set background=dark
set t_Co=256
"colorscheme solarized
"colorscheme molokai
"colorscheme Tomorrow-Night
"colorscheme Tomorrow-Night-Bright
"colorscheme desert



"设置标记一列的背景颜色和数字一行颜色一致
hi! link SignColumn   LineNr
hi! link ShowMarksHLl DiffAdd
hi! link ShowMarksHLu DiffChange

"" for error highlight,防止错误整行标红导致看不清
highlight clear SpellBad
highlight SpellBad term=standout ctermfg=1 term=underline cterm=underline
highlight clear SpellCap
highlight SpellCap term=underline cterm=underline
highlight clear SpellRare
highlight SpellRare term=underline cterm=underline
highlight clear SpellLocal
highlight SpellLocal term=underline cterm=underline

"C,C++, shell, python, javascript, ruby...等按F10运行
map <F10> :call CompileRun()<CR>
func! CompileRun()
    exec "w"
    if &filetype == 'c'
        exec "!g++ % -o %<"
        exec "!time ./%<"
        exec "!rm ./%<"
    elseif &filetype == 'cpp'
        exec "!g++ % -o %<"
        exec "!time ./%<"
        exec "!rm ./%<"
    elseif &filetype == 'java'
        exec "!javac %"
        exec "!time java %<"
        exec "!rm ./%<.class"
    elseif &filetype == 'sh'
        exec "!time bash %"
    elseif &filetype == 'python'
        exec "!time python %"
    elseif &filetype == 'html'
        exec "!chrome % &"
    elseif &filetype == 'go'
        exec "!go build %<"
        exec "!time go run %"
    elseif &filetype == 'mkd' "MarkDown 解决方案为VIM + Chrome浏览器的MarkDown Preview Plus插件,保存后实时预览
        exec "!chrome % &"
    elseif &filetype == 'javascript'
        exec "!time node %"
    elseif &filetype == 'coffee'
        exec "!time coffee %"
    elseif &filetype == 'ruby'
        exec "!time ruby %"
    endif
endfunc

_gvimrc

" An example for a gvimrc file.
" The commands in this are executed when the GUI is started.
"
" Maintainer:	Bram Moolenaar <Bram@vim.org>
" Last change:	2001 Sep 02
"
" To use it, copy it to
"     for Unix and OS/2:  ~/.gvimrc
"	      for Amiga:  s:.gvimrc
"  for MS-DOS and Win32:  $VIM\_gvimrc
"	    for OpenVMS:  sys$login:.gvimrc

" Make external commands work through a pipe instead of a pseudo-tty
"set noguipty

" set the X11 font to use
" set guifont=-misc-fixed-medium-r-normal--14-130-75-75-c-70-iso8859-1

set ch=1		" Make command line two lines high

"let g:skip_loading_mswin=1

"au BufAdd,BufNewFile * nested tab sball

set mousehide		" Hide the mouse when typing text

"set helplang=cn
"language chinese_china 
"set langmenu=zh_CN

"==========================================
" FileEncode Settings 文件编码,格式
"==========================================
" 设置新文件的编码为 UTF-8
set encoding=utf-8
" 自动判断编码时,依次尝试以下编码:
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
set helplang=cn
set langmenu=zh_CN.UTF-8
"set enc=2byte-gb18030
" 下面这句只影响普通模式 (非图形界面) 下的 Vim。
set termencoding=utf-8

" Use Unix as the standard file type
set ffs=unix,dos,mac

" 如遇Unicode值大于255的文本,不必等到空格再折行。
set formatoptions+=m
" 合并两行中文时,不在中间加空格:
set formatoptions+=B

"==========================================
" others 其它设置
"==========================================
autocmd! bufwritepost _vimrc source % " vimrc文件修改之后自动加载。 windows。
autocmd! bufwritepost _gvimrc source % 
autocmd! bufwritepost .vimrc source % " vimrc文件修改之后自动加载。 linux。

" 自动补全配置
"让Vim的补全菜单行为与一般IDE一致(参考VimTip1228)
set completeopt=longest,menu

" 增强模式中的命令行自动完成操作
set wildmenu

" Set extra options when running in GUI mode
if has("gui_running")
    set guifont=Monaco:h12
    if has("gui_gtk2")   "GTK2
        set guifont=Monaco\ 12,Monospace\ 12
    endif
    set guioptions-=T
    set guioptions+=e
    "set guioptions-=r
    "set guioptions+=b
    set guioptions-=L
    set guitablabel=%M\ %t
    set showtabline=1
    set linespace=2
    set noimd
    set t_Co=256
endif

" Ctrl + PageDown, 降低透明度
map <C-PageDown> :call SetAlpha('DOWN')<CR>
" Ctrl + PageUP, 增加透明度
map <C-PageUp> :call SetAlpha('UP')<CR>
" F12, 窗口置顶
map <F12> :call EnableTopMost()<CR>
" F11,  最大化
map <F11> :call Maximized()<CR>
" Ctrl + S 保存
map <C-S> :w<CR>
 
" 窗口透明度
let s:WindowAlpha=230
" 顶层标志
let s:IsTop = 0

let s:IsMax = 0

function! SetAlpha(updown)
    if a:updown == 'UP'
        let s:WindowAlpha += 20
        if s:WindowAlpha >= 255
            let s:WindowAlpha = 255
        endif
        :call libcallnr("vimtweak.dll", "SetAlpha", s:WindowAlpha)
        echo 'Window Alpha:'.s:WindowAlpha
    elseif a:updown == 'DOWN'
        let s:WindowAlpha -= 20
        if s:WindowAlpha <= 50
            let s:WindowAlpha = 50
        endif
        :call libcallnr("vimtweak.dll", "SetAlpha", s:WindowAlpha)
        echo 'Window Alpha:'.s:WindowAlpha
    endif
endfunction
 
function! EnableTopMost()
    if s:IsTop == 0
        :call libcallnr("vimtweak.dll", "EnableTopMost", 1)
        echo 'Enable Topmost'
        let s:IsTop = 1
    else
        :call libcallnr("vimtweak.dll", "EnableTopMost", 0)
        echo 'Disable Topmost'
        let s:IsTop = 0
    endif
endfunction

function! Maximized()
    if s:IsMax == 0
        :call libcallnr("vimtweak.dll", "EnableMaximize", 1)
        echo 'Maximized'
        let s:IsMax = 1
    else
        :call libcallnr("vimtweak.dll", "EnableMaximize", 0)
        echo 'Normal'
        let s:IsMax = 0
    endif
endfunction

" Make shift-insert work like in Xterm
map <S-Insert> <MiddleMouse>
map! <S-Insert> <MiddleMouse>

" Only do this for Vim version 5.0 and later.
if version >= 500

  " I like highlighting strings inside C comments
  let c_comment_strings=1

  " Switch on syntax highlighting if it wasn't on yet.
  if !exists("syntax_on")
    syntax on
  endif

  " Switch on search pattern highlighting.
  set hlsearch

  " For Win32 version, have "K" lookup the keyword in a help file
  "if has("win32")
  "  let winhelpfile='windows.hlp'
  "  map K :execute "!start winhlp32 -k <cword> " . winhelpfile <CR>
  "endif

  " Set nice colors
  " background for normal text is light grey
  " Text below the last line is darker grey
  " Cursor is green, Cyan when ":lmap" mappings are active
  " Constants are not underlined but have a slightly lighter background
    highlight Normal guibg=grey90
    highlight Cursor guibg=Green guifg=NONE
    highlight lCursor guibg=Cyan guifg=NONE
    highlight NonText guibg=grey80
    highlight Constant gui=NONE guibg=grey95
    highlight Special gui=NONE guibg=grey95

endif

vimrc.bundles

" ==========================================
" bundle 插件管理和配置项
" ==========================================

"------------------------------------------- begin of configs --------------------------------------------

" ################### 包依赖 #####################
" package dependence:  ctags, ag(he_silver_searcher)
" python dependence:   pep8, pyflake

" 非兼容vi模式。去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')


" ################### 插件管理 ###################

" 使用Vundle来管理插件
" vim plugin bundle control, command model
"     :BundleInstall     install 安装配置的插件
"     :BundleInstall!    update  更新
"     :BundleClean       remove plugin not in list 删除本地无用插件
Plugin 'gmarik/vundle'


" ################### 基础 ######################

" 多语言语法检查
"Bundle 'scrooloose/syntastic'
"let g:syntastic_error_symbol='>>'
"let g:syntastic_warning_symbol='>'
"let g:syntastic_check_on_open=1
"let g:syntastic_check_on_wq=0
"let g:syntastic_enable_highlighting=1

" 最轻量
" let g:syntastic_python_checkers=['pyflakes'] " 使用pyflakes

" 中等
" error code: http://pep8.readthedocs.org/en/latest/intro.html#error-codes
"let g:syntastic_python_checkers=['pyflakes', 'pep8'] " 使用pyflakes,速度比pylint快
"let g:syntastic_python_pep8_args='--ignore=E501,E225'

" 重量级, 但是足够强大, 定制完成后相当个性化
" pylint codes: http://pylint-messages.wikidot.com/all-codes
" let g:syntastic_python_checkers=['pyflakes', 'pylint'] " 使用pyflakes,速度比pylint快
" let g:syntastic_python_checkers=['pylint'] " 使用pyflakes,速度比pylint快
" let g:syntastic_python_pylint_args='--disable=C0111,R0903,C0301'


"let g:syntastic_javascript_checkers = ['jsl', 'jshint']
"let g:syntastic_html_checkers=['tidy', 'jshint']
" 修改高亮的背景色, 适应主题
"highlight SyntasticErrorSign guifg=white "guibg=black

" to see error location list
"let g:syntastic_always_populate_loc_list = 0
"let g:syntastic_auto_loc_list = 0
"let g:syntastic_loc_list_height = 5
"
"function! ToggleErrors()
"    let old_last_winnr = winnr('$')
"    lclose
"    if old_last_winnr == winnr('$')
"        " Nothing was closed, open syntastic error location panel
"        Errors
"    endif
"endfunction
"nnoremap <Leader>s :call ToggleErrors()<cr>
" nnoremap <Leader>sn :lnext<cr>
" nnoremap <Leader>sp :lprevious<cr>



" ################### 自动补全 ###################

" 代码自动补全
"迄今为止用到的最好的自动VIM自动补全插件
"重启 :YcmRestartServer
Bundle 'Valloric/YouCompleteMe'
"youcompleteme  默认tab  s-tab 和自动补全冲突
"let g:ycm_key_list_select_completion=['<c-n>']
let g:ycm_key_list_select_completion = ['<Down>']
"let g:ycm_key_list_previous_completion=['<c-p>']
let g:ycm_key_list_previous_completion = ['<Up>']
let g:ycm_complete_in_comments = 1  "在注释输入中也能补全
let g:ycm_complete_in_strings = 1   "在字符串输入中也能补全
"let g:ycm_use_ultisnips_completer = 1 "提示UltiSnips
let g:ycm_collect_identifiers_from_comments_and_strings = 1   "注释和字符串中的文字也会被收入补全
let g:ycm_collect_identifiers_from_tags_files = 1
let g:ycm_confirm_extra_conf = 0

"let g:ycm_seed_identifiers_with_syntax=1   "语言关键字补全, 不过python关键字都很短,所以,需要的自己打开

" 跳转到定义处, 分屏打开
let g:ycm_goto_buffer_command = 'horizontal-split'
" nnoremap <leader>jd :YcmCompleter GoToDefinition<CR>
nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR>
nnoremap <leader>gd :YcmCompleter GoToDeclaration<CR>

" 引入,可以补全系统,以及python的第三方包 针对新老版本YCM做了兼容
" old version
"if !empty(glob("~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py"))
"    let g:ycm_global_ycm_extra_conf = "~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py"
"endif
" new version
if !empty(glob("~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py"))
    let g:ycm_global_ycm_extra_conf = "~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py"
endif

" 直接触发自动补全 insert模式下
" let g:ycm_key_invoke_completion = '<C-Space>'
" 黑名单,不启用
let g:ycm_filetype_blacklist = {
      \ 'tagbar' : 1,
      \ 'gitcommit' : 1,
      \}


" 代码片段快速插入 (snippets中,是代码片段资源,需要学习)
"Bundle 'SirVer/ultisnips'
" Snippets are separated from the engine. Add this if you want them:
"Bundle 'honza/vim-snippets'

"let g:UltiSnipsExpandTrigger       = "<tab>"
"let g:UltiSnipsJumpForwardTrigger  = "<tab>"
"let g:UltiSnipsJumpBackwardTrigger = "<s-tab>"
"let g:UltiSnipsSnippetDirectories  = ['UltiSnips']
"let g:UltiSnipsSnippetsDir = '~/.vim/UltiSnips'
" 定义存放代码片段的文件夹 .vim/UltiSnips下,使用自定义和默认的,将会的到全局,有冲突的会提示
" 进入对应filetype的snippets进行编辑
"map <leader>us :UltiSnipsEdit<CR>

" ctrl+j/k 进行选择
"func! g:JInYCM()
"    if pumvisible()
"        return "\<C-n>"
"    else
"        return "\<c-j>"
"    endif
"endfunction
"
"func! g:KInYCM()
"    if pumvisible()
"        return "\<C-p>"
"    else
"        return "\<c-k>"
"    endif
"endfunction
"inoremap <c-j> <c-r>=g:JInYCM()<cr>
"au BufEnter,BufRead * exec "inoremap <silent> " . g:UltiSnipsJumpBackwordTrigger . " <C-R>=g:KInYCM()<cr>"
"let g:UltiSnipsJumpBackwordTrigger = "<c-k>"


" 自动补全单引号,双引号等
"Bundle 'Raimondi/delimitMate'

"" for python docstring ",优化输入
"au FileType python let b:delimitMate_nesting_quotes = ['"']
" 关闭某些类型文件的自动补全
"au FileType mail let b:delimitMate_autoclose = 0


" 自动补全html/xml标签
"Bundle 'docunext/closetag.vim'
"let g:closetag_html_style=1

" ################### 快速编码 ###################

" 快速注释
"Bundle 'scrooloose/nerdcommenter'
"let g:NERDSpaceDelims=1


" 快速加入修改环绕字符
"Bundle 'tpope/vim-surround'
" for repeat -> enhance surround.vim, . to repeat command
"Bundle 'tpope/vim-repeat'

" 快速去行尾空格 [, + <Space>]
"Bundle 'bronson/vim-trailing-whitespace'
"map <leader><space> :FixWhitespace<cr>

" 快速赋值语句对齐
"Bundle 'junegunn/vim-easy-align'
"vmap <Leader>a <Plug>(EasyAlign)
"nmap <Leader>a <Plug>(EasyAlign)
"if !exists('g:easy_align_delimiters')
"  let g:easy_align_delimiters = {}
"endif
"let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignore_groups': ['String'] }

" ################### 快速移动 ###################

"更高效的移动 [,, + w/fx]
"Bundle 'Lokaltog/vim-easymotion'
"let g:EasyMotion_smartcase = 1
"let g:EasyMotion_startofline = 0 " keep cursor colum when JK motion
"map <Leader><leader>h <Plug>(easymotion-linebackward)
"map <Leader><Leader>j <Plug>(easymotion-j)
"map <Leader><Leader>k <Plug>(easymotion-k)
"map <Leader><leader>l <Plug>(easymotion-lineforward)
" 重复上一次操作, 类似repeat插件, 很强大
"map <Leader><leader>. <Plug>(easymotion-repeat)



"Bundle 'vim-scripts/matchit.zip'

" 显示marks - 方便自己进行标记和跳转
" m[a-zA-Z] add mark
" '[a-zA-Z] go to mark
" m<Space>  del all marks
"Bundle "kshenoy/vim-signature"

" ################### 文本对象 ###################

" 支持自定义文本对象
"Bundle 'kana/vim-textobj-user.git'
" 增加行文本对象: l   dal yal cil
"Bundle 'kana/vim-textobj-line'
" 增加文件文本对象: e   dae yae cie
"Bundle 'kana/vim-textobj-entire.git'
" 增加缩进文本对象: i   dai yai cii - 相同缩进属于同一块
"Bundle 'kana/vim-textobj-indent.git'

" ################### 快速选中 ###################
" 选中区块
"Bundle 'terryma/vim-expand-region'
" map + <Plug>(expand_region_expand)
" map _ <Plug>(expand_region_shrink)
"vmap v <Plug>(expand_region_expand)
"vmap V <Plug>(expand_region_shrink)

" 多光标选中编辑
"Bundle 'terryma/vim-multiple-cursors'
"let g:multi_cursor_use_default_mapping=0
" Default mapping
"let g:multi_cursor_next_key='<C-m>'
"let g:multi_cursor_prev_key='<C-p>'
"let g:multi_cursor_skip_key='<C-x>'
"let g:multi_cursor_quit_key='<Esc>'

" ################### 功能相关 ###################

" 文件搜索
" change to https://github.com/ctrlpvim/ctrlp.vim
"Bundle 'ctrlpvim/ctrlp.vim'
"let g:ctrlp_map = '<leader>p'
"let g:ctrlp_cmd = 'CtrlP'
"map <leader>f :CtrlPMRU<CR>
"let g:ctrlp_custom_ignore = {
"    \ 'dir':  '\v[\/]\.(git|hg|svn|rvm)$',
"    \ 'file': '\v\.(exe|so|dll|zip|tar|tar.gz|pyc)$',
"    \ }
"let g:ctrlp_working_path_mode=0
"let g:ctrlp_match_window_bottom=1
"let g:ctrlp_max_height=15
"let g:ctrlp_match_window_reversed=0
"let g:ctrlp_mruf_max=500
"let g:ctrlp_follow_symlinks=1
" 如果安装了ag, 使用ag
" if executable('ag')
  " " Use ag in CtrlP for listing files. Lightning fast and respects .gitignore
  " let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
  " " ag is fast enough that CtrlP doesn't need to cache
  " let g:ctrlp_use_caching = 0
" endif


" ctrlp插件1 - 不用ctag进行函数快速跳转
"Bundle 'tacahiroy/ctrlp-funky'
"nnoremap <Leader>fu :CtrlPFunky<Cr>
" narrow the list down with a word under cursor
"nnoremap <Leader>fU :execute 'CtrlPFunky ' . expand('<cword>')<Cr>
"let g:ctrlp_funky_syntax_highlight = 1

"let g:ctrlp_extensions = ['funky']

" 类似sublimetext的搜索
"Bundle "dyng/ctrlsf.vim"
" In CtrlSF window:
" 回车/o, 打开
" t       在tab中打开(建议)
" T - Lkie t but focus CtrlSF window instead of opened new tab.
" q - Quit CtrlSF window.
"nmap \ <Plug>CtrlSFCwordPath<CR>
" let g:ctrlsf_position = 'below'
" let g:ctrlsf_winsize = '30%'
"let g:ctrlsf_auto_close = 0
"let g:ctrlsf_confirm_save = 0
" Note: cannot use <CR> or <C-m> for open
" Use : <sapce> or <tab>
"let g:ctrlsf_mapping = {
"    \ "open"  : "<Space>",
"    \ "openb" : "O",
"    \ "tab"   : "t",
"    \ "tabb"  : "T",
"    \ "prevw" : "p",
"    \ "quit"  : "q",
"    \ "next"  : "<C-J>",
"    \ "prev"  : "<C-K>",
"    \ "pquit" : "q",
"    \ }


" git.  git操作还是习惯命令行,vim里面处理简单diff编辑操作
" :Gdiff  :Gstatus :Gvsplit
"Bundle 'tpope/vim-fugitive'
"nnoremap <leader>ge :Gdiff<CR>
" not ready to open
" <leader>gb maps to :Gblame<CR>
" <leader>gs maps to :Gstatus<CR>
" <leader>gd maps to :Gdiff<CR>  和现有冲突
" <leader>gl maps to :Glog<CR>
" <leader>gc maps to :Gcommit<CR>
" <leader>gp maps to :Git push<CR>

" 同git diff,实时展示文件中修改的行
" 只是不喜欢除了行号多一列, 默认关闭,gs时打开
"Bundle 'airblade/vim-gitgutter'
"let g:gitgutter_map_keys = 0
"let g:gitgutter_enabled = 0
"let g:gitgutter_highlight_lines = 1
"nnoremap <leader>gs :GitGutterToggle<CR>

" edit history, 可以查看回到某个历史状态
"Bundle 'sjl/gundo.vim'
"noremap <leader>h :GundoToggle<CR>

" ################### 显示增强 ###################

" 状态栏增强展示
" 新的airline配置
"Bundle 'bling/vim-airline'
"if !exists('g:airline_symbols')
"    let g:airline_symbols = {}
"endif
"let g:airline_left_sep = '▶'
"let g:airline_left_alt_sep = '❯'
"let g:airline_right_sep = '◀'
"let g:airline_right_alt_sep = '❮'
"let g:airline_symbols.linenr = '¶'
"let g:airline_symbols.branch = '⎇'
" 是否打开tabline
" let g:airline#extensions#tabline#enabled = 1



" 括号显示增强
"Bundle 'kien/rainbow_parentheses.vim'
" 不加入这行, 防止黑色括号出现, 很难识别
" \ ['black',       'SeaGreen3'],
"let g:rbpt_colorpairs = [
"    \ ['brown',       'RoyalBlue3'],
"    \ ['Darkblue',    'SeaGreen3'],
"    \ ['darkgray',    'DarkOrchid3'],
"    \ ['darkgreen',   'firebrick3'],
"    \ ['darkcyan',    'RoyalBlue3'],
"    \ ['darkred',     'SeaGreen3'],
"    \ ['darkmagenta', 'DarkOrchid3'],
"    \ ['brown',       'firebrick3'],
"    \ ['gray',        'RoyalBlue3'],
"    \ ['darkmagenta', 'DarkOrchid3'],
"    \ ['Darkblue',    'firebrick3'],
"    \ ['darkgreen',   'RoyalBlue3'],
"    \ ['darkcyan',    'SeaGreen3'],
"    \ ['darkred',     'DarkOrchid3'],
"    \ ['red',         'firebrick3'],
"    \ ]
"
"let g:rbpt_max = 16
"let g:rbpt_loadcmd_toggle = 0
"au VimEnter * RainbowParenthesesToggle
"au Syntax * RainbowParenthesesLoadRound
"au Syntax * RainbowParenthesesLoadSquare
"au Syntax * RainbowParenthesesLoadBraces


" ################### 显示增强-主题 ###################"

" 主题 solarized
Bundle 'altercation/vim-colors-solarized'
let g:solarized_termtrans=1
let g:solarized_contrast="normal"
let g:solarized_visibility="normal"
" let g:solarized_termcolors=256

" 主题 molokai
Bundle 'tomasr/molokai'
" monokai原始背景色
let g:molokai_original = 1

" 主题 tomorrow
Bundle 'chriskempson/vim-tomorrow-theme'


" ################### 快速导航 ###################
"目录导航
"Bundle 'scrooloose/nerdtree'
"map <leader>n :NERDTreeToggle<CR>
"let NERDTreeHighlightCursorline=1
"let NERDTreeIgnore=[ '\.pyc$', '\.pyo$', '\.obj$', '\.o$', '\.so$', '\.egg$', '^\.git$', '^\.svn$', '^\.hg$' ]
"close vim if the only window left open is a NERDTree
"autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | end
" s/v 分屏打开文件
"let g:NERDTreeMapOpenSplit = 's'
"let g:NERDTreeMapOpenVSplit = 'v'


"Bundle 'jistr/vim-nerdtree-tabs'
"map <Leader>n <plug>NERDTreeTabsToggle<CR>
" 关闭同步
"let g:nerdtree_tabs_synchronize_view=0
"let g:nerdtree_tabs_synchronize_focus=0
" 自动开启nerdtree
"let g:nerdtree_tabs_open_on_console_startup=1


" Vim Workspace Controller
"Bundle "szw/vim-ctrlspace"
"let g:airline_exclude_preview = 1
"hi CtrlSpaceSelected guifg=#586e75 guibg=#eee8d5 guisp=#839496 gui=reverse,bold ctermfg=10 ctermbg=7 cterm=reverse,bold
"hi CtrlSpaceNormal   guifg=#839496 guibg=#021B25 guisp=#839496 gui=NONE ctermfg=12 ctermbg=0 cterm=NONE
"hi CtrlSpaceSearch   guifg=#cb4b16 guibg=NONE gui=bold ctermfg=9 ctermbg=NONE term=bold cterm=bold
"hi CtrlSpaceStatus   guifg=#839496 guibg=#002b36 gui=reverse term=reverse cterm=reverse ctermfg=12 ctermbg=8


" for minibufferexpl 去掉, 有需要同学的自己解开
" Bundle 'fholgado/minibufexpl.vim'
" let g:miniBufExplMapWindowNavVim = 1
" let g:miniBufExplMapWindowNavArrows = 1
" let g:miniBufExplMapCTabSwitchBufs = 1
" let g:miniBufExplModSelTarget = 1
" " 解决FileExplorer窗口变小问题
" let g:miniBufExplForceSyntaxEnable = 1
" let g:miniBufExplorerMoreThanOne=2
" let g:miniBufExplCycleArround=1
" " 默认方向键左右可以切换buffer
" nnoremap <TAB> :MBEbn<CR>
" noremap <leader>bn :MBEbn<CR>
" noremap <leader>bp :MBEbp<CR>
" noremap <leader>bd :MBEbd<CR>


" 标签导航
"Bundle 'majutsushi/tagbar'
"nmap <F9> :TagbarToggle<CR>
"let g:tagbar_autofocus = 1
" for ruby
"let g:tagbar_type_ruby = {
"    \ 'kinds' : [
"        \ 'm:modules',
"        \ 'c:classes',
"        \ 'd:describes',
"        \ 'C:contexts',
"        \ 'f:methods',
"        \ 'F:singleton methods'
"    \ ]
"\ }

" go语言的tagbar配置
" 1. install gotags 'go get -u github.com/jstemmer/gotags'
" 2. make sure `gotags` in you shell PATH, you can call check it with `which gotags`
" for gotags. work with tagbar
"let g:tagbar_type_go = {
"    \ 'ctagstype' : 'go',
"    \ 'kinds'     : [
"        \ 'p:package',
"        \ 'i:imports:1',
"        \ 'c:constants',
"        \ 'v:variables',
"        \ 't:types',
"        \ 'n:interfaces',
"        \ 'w:fields',
"        \ 'e:embedded',
"        \ 'm:methods',
"        \ 'r:constructor',
"        \ 'f:functions'
"    \ ],
"    \ 'sro' : '.',
"    \ 'kind2scope' : {
"        \ 't' : 'ctype',
"        \ 'n' : 'ntype'
"    \ },
"    \ 'scope2kind' : {
"        \ 'ctype' : 't',
"        \ 'ntype' : 'n'
"    \ },
"    \ 'ctagsbin'  : 'gotags',
"    \ 'ctagsargs' : '-sort -silent'
"\ }


" 去除taglist =>原因: 使用tagbar和ctrlp-funky可以直接快速跳转函数和变量位置,taglist有些多余

" ################### 语言相关 ###################

"Bundle 'thinca/vim-quickrun'
"let g:quickrun_config = {
"\   "_" : {
"\       "outputter" : "message",
"\   },
"\}

"let g:quickrun_no_default_key_mappings = 1
"nmap <Leader>r <Plug>(quickrun)
"map <F10> :QuickRun<CR>

" ###### Python #########

" python fly check, 弥补syntastic只能打开和保存才检查语法的不足
"Bundle 'kevinw/pyflakes-vim'
"let g:pyflakes_use_quickfix = 0

" for python.vim syntax highlight
"Bundle 'hdima/python-syntax'
"let python_highlight_all = 1

" ###### Golang #########
" 1.install golang and install gocode 'go get github.com/nsf/gocode'
" 2.make sure gocode in your path: `which gocode` (add $GOPATH/bin to you $PATH)
"Bundle 'Blackrush/vim-gocode'
" Bundle 'fatih/vim-go.git'

" ###### Ruby #########
" Bundle 'vim-ruby/vim-ruby'
" Bundle 'nelstrom/vim-textobj-rubyblock'

" 有bug, 和当前有冲突, 尚未解决, 不要打开
" Bundle 'tpope/vim-endwise'


" ###### Markdown #########
Bundle 'plasticboy/vim-markdown'
let g:vim_markdown_folding_disabled=1

" https://github.com/suan/vim-instant-markdown
" npm -g install instant-markdown-d
" Bundle 'suan/vim-instant-markdown'
" let g:instant_markdown_slow = 1
" let g:instant_markdown_autostart = 0
" map <F12> :InstantMarkdownPreview<CR>

" ###### HTML/JS/JQUERY/CSS #########

" for javascript  注意: syntax这个插件要放前面
"Bundle 'jelera/vim-javascript-syntax'
"Bundle "pangloss/vim-javascript"
"let g:html_indent_inctags = "html,body,head,tbody"
"let g:html_indent_script1 = "inc"
"let g:html_indent_style1 = "inc"


" for javascript 自动补全,配合YCM,需要安装nodejs&npm  see
" https://github.com/marijnh/tern_for_vim
" Bundle 'marijnh/tern_for_vim'

" for jquery
"Bundle 'nono/jquery.vim'

" ###### emmet HTML complete #########
" Bundle "mattn/emmet-vim"

" ###### vim.less : less 自动更新##########
" Bundle 'groenewege/vim-less'
" autocmd BufWritePost *.less :!lessc % > %:p:r.css

" ###### Jinja2 #########
"Bundle 'Glench/Vim-Jinja2-Syntax'

" for css color
" not work in iterm2 which termianl selection is not xterm-256
" Bundle 'ap/vim-css-color'

" 这个有坑, see issue https://github.com/wklken/k-vim/issues/49
" Bundle 'gorodinskiy/vim-coloresque'

" ###### nginx #########
" Bundle 'evanmiller/nginx-vim-syntax'


" ####### temp #######
" python code format
" autocmd FileType python nnoremap <leader>y :0,$!yapf --stdout-encoding=utf-8<Cr>
" autocmd FileType python nnoremap <leader>y :0,$!yapf<Cr>
" Bundle 'mindriot101/vim-yapf'
" scriptencoding utf-8
" let g:yapf_style = "google"
" let g:yapf_style = "pep8"
" setenv PYTHONIOENCODING UTF-8
" nnoremap <leader>y :call Yapf()<cr>

" Bundle 'amoffat/snake'

call vundle#end()
"------------------------------------------- end of configs --------------------------------------------

2.3安装插件

2.3.1 汉化与背景透明

汉化分两部分,一部分是菜单,一部分是用户手册汉化。只给出下载路径,怎么安装,自己看README研究去。

vimcdoc-1.9.0.tar.gz 这里下载。其主页是这里

背景透明,主要是sublime text我配置的是背景透明的,编译完gvim后顺手一搜,发现了vimtweak.它提供是dll我们应该是没法用的,我们编译一个64位的版本。需要用把_declspec(dllexport)改成__declspec( dllexport )。然后使用MingW-W64的64位编译器make下就可,最后还可以运行下strip vimtweak.dll 可以从78k优化成18k。

2.3.2Vundle与其他插件安装

启动一个命令行切换到E:\vim-home下面,即vim的HOME目录

git clone https://github.com/gmarik/Vundle.vim.git  .vim/vundle/Vundle.vim 

启动一个命令行换到E:\vim74下面,即vim的安装目录。执行如下命令行(必须执行gvim.bat而不是gvim.exe,否则没有任何效果)

 gvim.bat +PluginInstall +qall 

如果一切正常,那么我们在E:\vim-home下面看到一个.vim目录.

3.编译ycmd

3.1安装llvm3.6到Visual Studio

起初我还不确定,现在完全确定这是需要的。简单来说就是确认,如果我们要编译llvm/clang最新的源码,我们只用Visual Studio自己的工具链是不行的。但是Visual Studio是开放的,可以设置其他编译的,比如Intel Compiler就是这么干的。然而我们llvm的官方也发布一个这样的编译器,在Visual Studio中支持clang编译器,虽然问题很多,但是编译llvm/clang自己,必须用自己来编译(除非你用MingW-W64).

LLVM-3.6.1-win32.exe 这个文件很小36.8M,需要去这个页面下载。然后安装任意地方都可以,它会注册一个Visual Studio的编译器,它具体怎么设置我没研究,但是以后Visual Studio打开文件的时候会发现编译选项多了4个,其中一个就是LLVM-vs2013。

3.2编译llvm/clang

在E:\vim-home下面新建_build_llvm.bat文件,内容如下:

@echo off
cd /d %~dp0

REM Follow http://clang.llvm.org/get_started.html
REM clone the latest llvm/clang source code take about 361MB disk space
IF NOT EXIST llvm-src (
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm-src
cd llvm-src\tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
cd ..\..
)

if not exist llvm_build mkdir llvm_build
cd llvm_build

set PATH_BACKUP=%path%
set PATH=C:\Program Files (x86)\CMake\bin;

REM open in Visual studio 2013 and build, it will take about 6.65GB disk space
cmake -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 12 2013 Win64" ..\llvm-src

IF ERRORLEVEL 1 goto ERROR

rem IF [%1]==[] goto QUIT

SET PATH=%PATH_BACKUP%
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64

devenv LLVM.sln /build release /project ALL_BUILD

IF ERRORLEVEL 1 goto ERROR
IF ERRORLEVEL 0 goto QUIT
:ERROR
echo Error!
pause
:QUIT
rem exit

双击_build_llvm.bat运行,其功能是下载最新的llvm/clang脚本(连带.svn目录,大小是360+MB),然后自动编译,占用大约2.40GB磁盘空间。

正常的正确运行是自动退出,如果出错,则会停住。运行结束我们应该看到一个llvm-src和llvm_build.

3.3编译ycmd

在E:\vim-home下面新建一个_build_ycmd.bat文件,内容如下:

@echo off
cd %~dp0
SET TOOLDIR=E:\vim_tools

SET LLVM_PATH=%~dp0\llvm_build\Release

xcopy %~dp0\llvm-src\include %LLVM_PATH%\include  /D /E /H /I /Y
xcopy %~dp0\llvm-src\tools\clang\include %LLVM_PATH%\include  /D /E /H /I /Y

set PATH_BACKUP=%path%
SET PATH=C:\Program Files (x86)\CMake\bin;

if not exist ycmd_build mkdir ycmd_build
cd ycmd_build

cmake  -DPATH_TO_LLVM_ROOT=%~dp0\llvm_build\Release -G "Visual Studio 12 2013 Win64" ..\.vim\bundle\YouCompleteMe\third_party\ycmd\cpp

IF ERRORLEVEL 1 goto ERROR

rem IF [%1]==[] goto QUIT

SET PATH=%PATH_BACKUP%
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64

devenv YouCompleteMe.sln /build release /project ycm_support_libs

IF ERRORLEVEL 1 goto ERROR
IF ERRORLEVEL 0 goto QUIT

:ERROR

echo Error!

pause

:QUIT
rem exit

正常的正确运行是自动退出,如果出错,则会停住。运行结束我们应该看到一个ycmd_build.

然后我们去E:\vim-home\.vim\bundle\YouCompleteMe\third_party\ycmd这个目录检验我们的成果。正常的应该看到

libclang.dll

ycm_client_support.pyd

ycm_core.pyd

三个文件,那么我们本文最核心的目标就达成了。另外可以安全地删除E:\vim-home\llvm-src,E:\vim-home\ycmd_build但是,E:\vim-home\llvm_build不推荐删除,因为我们需要,E:\vim-home\llvm_build\Release目录,复制其内容到E:\vim_tools\llvim3.7.0,使E:\vim_tools\llvim3.7.0看起来如下:

bin/

include/

libs/

然后我们可以删除libs目录,ycmd不需要libs目录。

4.快捷键

除了k-vim的绝大部分快捷键,另外有:

F11最大化/普通

F12总在最前/普通

Ctrl+PageUp 减小透明度

Ctrl+PageDown增加透明度

Ctrl+S保存

5.bugs

“`bash

Runtime Error!

Program: $VIM\gvim.exe

R6034

An application has made an attempt to load the C runtime

library incorrectly.

Please contact the application’s support team for more

information.

“`

参考这里

在我机器上面是 `C:\Program Files (x86)\Intel\iCLS Client\msvcr90.dll`. 把`C:\Program Files (x86)\Intel\iCLS Client` 从系统的PATH删除即可.

GVIM演示

GVIM演示

vimim中文输入法

vimim中文输入法

xpm图像

xpm图像

本文链接:在Visual Studio编译gvim和ycmd

转载声明:本站文章若无特别说明,皆为原创,转载请注明来源:Rexdf,谢谢!^^


此条目发表在编程日志分类目录,贴了, 标签。将固定链接加入收藏夹。

9 Responses to 在Visual Studio编译gvim和ycmd

发表回复

您的电子邮箱地址不会被公开。

*

:zsmilebig: :zsadbig: :zwiredbig: :zgreenhappy: more »

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据