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

