近期对VIM进行设置,增加了一键编译/运行/调试等功能,配置部分快捷键如下:
Zz 同ZZ,在正常模式下快速保存退出
Zq 同Zq,正常模式下快速不保存退出
\\ 取消本次当前高亮显示
\/ 尝试从自定义的.vimcfg配置文件中读取PATH和PATH+值并设置文件查找路径path
\. 将工作目录转为当前文件目录
\hh 在命令行中输入替换命令模板s///gc
\hc 在命令行中输入替换命令模板s/当前光标下的词/当前光标下的词/gc
\hv 在命令行中输入替换命令模板s/最近一次复制或删除的词/最近一次复制或删除的词/gc
\y Visual模式下复制到系统剪切板(需要+clipboard属性)
\v Normal模式下从系统剪切板粘贴(需要+clipboard属性)
F2 在右侧分割窗口打开文件浏览界面
\F2 在新标签页(Tab)打开文件浏览界面
F3 快速保存当前文件
\F3 快速保存全部文件
F4 去掉每行尾部的空白字符
\F4 去掉全部空白行
F5 对可编译的文件进行编译
Ctrl-F5 运行ctags生成tags文件
F6 执行编译好的文件(通过cmake、configure、make等编译时无法自动找到可执行文件)
F7 启动调试(通过cmake、configure、make等编译时需要用file命令手动加载可执行文件)
F8 打开文件浏览窗口
Ctrl-F8 打开或关闭QuickFix窗口
将以下代码复制到~/.vimrc文件即可生效(注意备份原.vimrc文件)。
"----------------------------------------------------------------------- autocmd BufWritePost $MYVIMRC source $MYVIMRC autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exec "normal! g`\"" | endif filetype on syntax enable syntax on set nocompatible set noautochdir set showcmd set showmode set showtabline=2 set laststatus=2 set mouse=a set tags=./tags;,tags set hlsearch set incsearch set noignorecase set selection=inclusive set virtualedit=onemore set whichwrap+=h,l,<,>,[,] set wildmenu set wildmode=longest,list set completeopt=preview,menu,longest set expandtab set smarttab set autoindent set cindent set tabstop=4 set softtabstop=4 set shiftwidth=4 set scrolloff=8 set ruler set number set cursorline highlight LineNr cterm=none ctermfg=darkgray highlight CursorLineNr cterm=bold ctermfg=gray ctermbg=darkgray autocmd InsertEnter * highlight CursorLineNr cterm=bold ctermbg=darkblue autocmd InsertLeave * highlight CursorLineNr cterm=bold ctermbg=darkgray highlight CursorLine cterm=none ctermbg=darkgray autocmd InsertEnter * highlight CursorLine cterm=bold ctermbg=darkblue autocmd InsertLeave * highlight CursorLine cterm=none ctermbg=darkgray highlight TablineSel ctermfg=black ctermbg=white highlight Tabline ctermbg=gray highlight TablineFill ctermfg=black highlight StatusLine ctermfg=gray highlight StatusLineNC ctermfg=gray highlight VertSplit ctermfg=gray "----------------------------------------------------------------------- let g:mapleader='\' nnoremap <Del> i<Del> nnoremap q ^ nnoremap Q $ nnoremap Zz ZZ nnoremap Zq ZQ "nnoremap j k "nnoremap k j "nnoremap b <PageUp> "nnoremap n <PageDown> "nnoremap <Leader>i [<C-i> "nnoremap <Leader>d [<C-d> "inoremap <C-h> <Left> "inoremap <C-l> <Right> "inoremap <C-j> <Up> "inoremap <C-k> <Down> "inoremap <C-b> <PageUp> "inoremap <C-n> <PageDown> "vnoremap <C-t> :w !cat<CR> nnoremap <Leader><CR> i nnoremap <Leader><Leader> :nohl<CR> nnoremap <Leader>hh :%s///gc<Left><Left><Left><Left> vnoremap <Leader>hh :s///gc<Left><Left><Left><Left> nnoremap <Leader>hc :%s/\<<C-R><C-W>\>/<C-R><C-W>/gc<Left><Left><Left><Left> vnoremap <Leader>hc :s/\<<C-R><C-W>\>/<C-R><C-W>/gc<Left><Left><Left><Left> nnoremap <Leader>hv :%s/<C-R>"/<C-R>"/gc<Left><Left><Left><Left> vnoremap <Leader>hv :s/<C-R>"/<C-R>"/gc<Left><Left><Left><Left> vnoremap <Leader>y "+y nnoremap <Leader>v "+p noremap <silent><C-w> <Esc><C-w> noremap! <silent><C-w> <Esc><C-w> noremap <F2> <Esc>:botright vsp .<CR> noremap! <F2> <Esc>:botright vsp .<CR> nnoremap <Leader><F2> :tabnew .<CR> noremap <F3> <Esc>:w<CR> noremap! <F3> <Esc>:w<CR> nnoremap <Leader><F3> :wa<CR> noremap <F4> <Esc>:%s/\s\+$//g<CR> noremap! <F4> <Esc>:%s/\s\+$//g<CR> nnoremap <Leader><F4> :g/^\s*$/d<CR> "----------------------------------------------------------------------- function! GetCfg(file, key) if filereadable(a:file) for line in readfile(a:file) if line =~? '^'.a:key.'=' return substitute(line, '\c'.a:key.'=', '', '') endif endfor endif return '' endfunction function! SetPath() let path=GetCfg(expand('%:p').'.vimcfg', 'PATH') if path == '' let path=GetCfg('./.vimcfg', 'PATH') endif if path != '' let &path=path endif let path=GetCfg(expand('%:p').'.vimcfg', 'PATH+') if path == '' let path=GetCfg('./.vimcfg', 'PATH+') endif if path != '' && stridx(','.&path.',', ','.path.',') < 0 if &path =~ ',$' let &path=&path.path else let &path=&path.','.path endif endif endfunction "call SetPath() "autocmd BufReadPost * call SetPath() nnoremap <Leader>/ :call SetPath()\|set path<CR> nnoremap <Leader>. :cd %:p:h\|pwd<CR> "----------------------------------------------------------------------- function! GenMakeCmd() " filetype on " &filetype ==? expand('%:e') let ext=expand('%:e') if ext ==? 'c' || ext ==? 'cpp' || ext ==? 'cxx' || ext ==? 'cc' if filereadable(expand('%:p:h').'/CMakeLists.txt') if executable('/usr/bin/cmake') if !isdirectory(expand('%:p:h').'/build') call mkdir(expand('%:p:h').'/build') endif return 'cd "%:p:h/build" && cmake .. && make -j8' else echoerr 'Can not find "cmake"!' endif elseif executable(expand('%:p:h').'/configure') return 'cd "%:p:h" && ./configure && make -j8' elseif filereadable(expand('%:p:h').'/Makefile') \ || filereadable(expand('%:p:h').'/makefile') return 'cd "%:p:h" && make -j8' elseif filereadable('CMakeLists.txt') if executable('/usr/bin/cmake') if !isdirectory('build') call mkdir('build') endif return 'cd build && cmake .. && make -j8' else echoerr 'Can not find "cmake"!' endif elseif executable('./configure') return './configure && make -j8' elseif filereadable('Makefile') || filereadable('makefile') return 'make -j8' else if ext ==? 'c' return 'gcc --verbose -g3 -O0 -Wall -o "%<" "%"' else return 'g++ --verbose -g3 -O0 -Wall -o "%<" "%"' endif endif elseif ext ==? 'java' return 'javac -verbose -g "%"' elseif ext == '' echoerr 'Unknown file type: "'.@%.'"!' else echoerr 'Operation "make" on "*.'.ext.'" is not defined!' endif return '' endfunction let g:MAKE_CMD='' function! GetMakeCmd() if exists('g:MAKE_CMD') && g:MAKE_CMD != '' return g:MAKE_CMD endif let make_cmd=GetCfg(expand('%:p').'.vimcfg', 'MAKE_CMD') if make_cmd != '' return make_cmd endif let make_cmd=GetCfg('./.vimcfg', 'MAKE_CMD') if make_cmd != '' return make_cmd endif return GenMakeCmd() endfunction function! Make() exec 'update' redraw! let make_cmd=GetMakeCmd() if make_cmd != '' exec 'cclose' let &makeprg=make_cmd make! exec 'botright cwindow' return endif echoerr 'MAKE_CMD is not defined!' endfunction noremap <silent><F5> <Esc>:call Make()<CR> noremap! <silent><F5> <Esc>:call Make()<CR> "----------------------------------------------------------------------- function! Ctags() exec 'update' redraw! if executable('/usr/bin/ctags') exec '!ctags -R --c-kinds=+px --c++-kinds=+px --fields=+iaS --extra=+q \ && echo "CTags completed successfully."' else echoerr 'Can not find "ctags"!' endif endfunction noremap <silent><C-F5> <Esc>:call Ctags()<CR> noremap! <silent><C-F5> <Esc>:call Ctags()<CR> "----------------------------------------------------------------------- function! GenRunCmd() " filetype on " &filetype ==? expand('%:e') let ext=expand('%:e') if ext ==? 'c' || ext ==? 'cpp' || ext ==? 'cxx' || ext ==? 'cc' if filereadable(expand('%:p:h').'/CMakeLists.txt') echoerr '"CMakeLists.txt" has been found in directory "'.expand('%:p:h').'".' elseif executable(expand('%:p:h').'/configure') echoerr '"configure*" has been found in directory "'.expand('%:p:h').'".' elseif filereadable(expand('%:p:h').'/Makefile') \ || filereadable(expand('%:p:h').'/makefile') echoerr '"Makefile" has been found in directory "'.expand('%:p:h').'".' elseif filereadable('CMakeLists.txt') echoerr '"CMakeLists.txt" has been found in working directory "'.getcwd().'".' elseif executable('./configure') echoerr '"configure*" has been found in working directory "'.getcwd().'".' elseif filereadable('Makefile') || filereadable('makefile') echoerr '"Makefile" has been found in working directory "'.getcwd().'".' else if stridx(expand('%<'), '/') < 0 let exe_file='./'.expand('%<') else let exe_file=expand('%<') endif if executable(exe_file) return '"'.exe_file.'"' else echoerr 'Can not find executable file!' endif endif elseif ext ==? 'java' "return 'cd "'.expand('%:p:h').'" && java '.expand('%:t:r') return 'cd "%:p:h" && java %:t:r' elseif ext ==? 'py' return 'python "%"' elseif ext ==? 'sh' return 'bash "%"' elseif ext ==? 'html' return 'firefox "%" &' elseif ext == '' echoerr 'Unknown file type: "'.@%.'"!' else echoerr 'Operation "run" on "*.'.ext.'" is not defined!' endif return '' endfunction let g:RUN_CMD='' function! GetRunCmd() if exists('g:RUN_CMD') && g:RUN_CMD != '' return g:RUN_CMD endif let run_cmd=GetCfg(expand('%:p').'.vimcfg', 'RUN_CMD') if run_cmd != '' return run_cmd endif let run_cmd=GetCfg('./.vimcfg', 'RUN_CMD') if run_cmd != '' return run_cmd endif return GenRunCmd() endfunction function! Run() exec 'update' redraw! let run_cmd=GetRunCmd() if run_cmd != '' exec 'cclose' exec '!'.run_cmd return endif echoerr 'RUN_CMD is not defined!' endfunction noremap <silent><F6> <Esc>:call Run()<CR> noremap! <silent><F6> <Esc>:call Run()<CR> "----------------------------------------------------------------------- function! GenDebugCmd() " filetype on " &filetype ==? expand('%:e') let ext=expand('%:e') if ext ==? 'c' || ext ==? 'cpp' || ext ==? 'cxx' || ext ==? 'cc' if exists(':ConqueGdb') let debug_cmd='ConqueGdb' else let debug_cmd='gdb -tui' endif if filereadable(expand('%:p:h').'/CMakeLists.txt') return debug_cmd elseif executable(expand('%:p:h').'/configure') return debug_cmd elseif filereadable(expand('%:p:h').'/Makefile') \ || filereadable(expand('%:p:h').'/makefile') return debug_cmd elseif filereadable('CMakeLists.txt') return debug_cmd elseif executable('./configure') return debug_cmd elseif filereadable('Makefile') || filereadable('makefile') return debug_cmd else "if stridx(expand('%<'), '/') < 0 " let exe_file='./'.expand('%<') "else " let exe_file=expand('%<') "endif "if executable(exe_file) " return debug_cmd.' "'.exe_file.'"' "else " return debug_cmd "endif return debug_cmd.' "'.expand('%<').'"' endif elseif ext ==? 'java' "return 'cd "'.expand('%:p:h').'" && jdb '.expand('%:t:r') return 'cd "%:p:h" && jdb %:t:r' elseif ext ==? 'py' return 'python -m pdb "%"' elseif ext ==? 'sh' "return 'bashdb "%"' return 'bash -x "%"' elseif ext == '' echoerr 'Unknown file type: "'.@%.'"!' else echoerr 'Operation "debug" on "*.'.ext.'" is not defined!' endif return '' endfunction let g:DEBUG_CMD='' function! GetDebugCmd() if exists('g:DEBUG_CMD') && g:DEBUG_CMD != '' return g:DEBUG_CMD endif let debug_cmd=GetCfg(expand('%:p').'.vimcfg', 'DEBUG_CMD') if debug_cmd != '' return debug_cmd endif let debug_cmd=GetCfg('./.vimcfg', 'DEBUG_CMD') if debug_cmd != '' return debug_cmd endif return GenDebugCmd() endfunction function! Debug() exec 'update' redraw! let debug_cmd=GetDebugCmd() if debug_cmd != '' exec 'cclose' if debug_cmd =~ '^ConqueGdb' exec debug_cmd else exec '!'.debug_cmd endif return endif echoerr 'DEBUG_CMD is not defined!' endfunction noremap <silent><F7> <Esc>:call Debug()<CR> noremap! <silent><F7> <Esc>:call Debug()<CR> "----------------------------------------------------------------------- function! ExpToggle() if exists(':WMToggle') if exists(':Tlist') let g:winManagerWindowLayout='FileExplorer|TagList' else let g:winManagerWindowLayout='FileExplorer' endif WMToggle else let g:netrw_banner=0 let g:netrw_winsize=12 let g:netrw_liststyle=3 Lex endif endfunction let g:ConqueTerm_ToggleKey='<F12>' noremap <silent><F8> <Esc>:call ExpToggle()<CR> noremap! <silent><F8> <Esc>:call ExpToggle()<CR> "----------------------------------------------------------------------- autocmd QuickFixCmdPost * botright cwindow autocmd BufReadPost quickfix let t:qfix_win=bufnr('$') autocmd BufWinEnter quickfix let t:qfix_win=bufnr('$') autocmd BufWinLeave * if exists('t:qfix_win') && expand('<abuf>') == t:qfix_win | unlet! t:qfix_win | endif function! QFixToggle() if exists('t:qfix_win') cclose else botright copen endif endfunction noremap <silent><C-F8> <Esc>:call QFixToggle()<CR> noremap! <silent><C-F8> <Esc>:call QFixToggle()<CR> "-----------------------------------------------------------------------
编译、运行和调试三个命令的命令行按优先顺序如下设置:
1、设置g:MAKE_CMD/g:RUN_CMD/g:DEBUG_CMD三个变量,如let g:RUN_CMD='build/exec_file'。如果在命令行模式下输入则只对本次窗口有效,下次重启需要重新输入;如果在.vimrc文件中写入虽然不用每次重新输入,但是需要对不同的文件经常修改.vimrc文件。
2、在要编辑的文件filename.ext同目录下创建filename.ext.vimcfg配置文件,文件中配置MAKE_CMD/RUN_CMD/DEBUG_CMD,如make_cmd=pwd && make,这种方式适合对单独文件进行分别配置。
3、在工作目录下创建.vimcfg文件,文件中配置MAKE_CMD/RUN_CMD/DEBUG_CMD,这种方式适合按照项目组织的多个文件统一编译、运行和调试。
4、尝试根据filename.ext文件类型和CMakeLists.txt等文件自动生成MAKE_CMD/RUN_CMD/DEBUG_CMD:如果在文件目录或工作目录存在CMakeLists.txt、configure、makefile等配置文件,则利用其进行编译,但无法获得输出文件名,因为其可能输出多个文件,需要手工指定,否则默认可执行文件名为filename。
“\/”快捷键尝试从自定义的配置文件中读取PATH和PATH+值并设置文件查找路径path,这在利用gf命令打开包含(include)文件时很有用。具体设置是在.vimcfg或filename.ext.vimcfg文件中设置path=和path+=的值,“+”代表追加的意思,多个路径间用“,”分割,如path+=include,src。
最后,一个完整的.vimcfg文件设置示例如图所示: