近期對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文件設置示例如圖所示: