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