VIM增加一鍵編譯/運行/調試


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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM