1
0
Fork 0
mirror of synced 2024-07-05 15:01:09 -04:00
ultimate-vim/sources_non_forked/vim-cscope/plugin/cscope.vim
2017-04-10 21:02:38 +08:00

376 lines
9.9 KiB
VimL
Executable file

" vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab foldmethod=marker
" Copyright: Copyright (C) 2012-2015 Brook Hong
" License: The MIT License
"
if !exists('g:cscope_silent')
let g:cscope_silent = 0
endif
if !exists('g:cscope_auto_update')
let g:cscope_auto_update = 1
endif
if !exists('g:cscope_open_location')
let g:cscope_open_location = 1
endif
if !exists('g:cscope_split_threshold')
let g:cscope_split_threshold = 10000
endif
function! s:echo(msg)
if g:cscope_silent == 0
echo a:msg
endif
endfunction
function! ToggleLocationList()
let l:own = winnr()
lw
let l:cwn = winnr()
if(l:cwn == l:own)
if &buftype == 'quickfix'
lclose
elseif len(getloclist(winnr())) > 0
lclose
else
echohl WarningMsg | echo "No location list." | echohl None
endif
endif
endfunction
if !exists('g:cscope_cmd')
if executable('cscope')
let g:cscope_cmd = 'cscope'
else
call <SID>echo('cscope: command not found')
finish
endif
endif
if !exists('g:cscope_interested_files')
let files = readfile(expand("<sfile>:p:h")."/interested.txt")
let g:cscope_interested_files = join(map(files, 'v:val."$"'), '\|')
endif
let s:cscope_vim_dir = substitute($HOME,'\\','/','g')."/.cscope.vim"
let s:index_file = s:cscope_vim_dir.'/index'
function! s:GetBestPath(dir)
let f = substitute(a:dir,'\\','/','g')
let bestDir = ""
for d in keys(s:dbs)
if stridx(f, d) == 0 && len(d) > len(bestDir)
let bestDir = d
endif
endfor
return bestDir
endfunction
function! s:ListFiles(dir)
let d = []
let f = []
let cwd = a:dir
let sl = &l:stl
try
while cwd != ''
let a = split(globpath(cwd, "*"), "\n")
for fn in a
if getftype(fn) == 'dir'
if !exists('g:cscope_ignored_dir') || fn !~? g:cscope_ignored_dir
call add(d, fn)
endif
elseif getftype(fn) != 'file'
continue
elseif fn !~? g:cscope_interested_files
continue
else
if stridx(fn, ' ') != -1
let fn = '"'.fn.'"'
endif
call add(f, fn)
endif
endfor
let cwd = len(d) ? remove(d, 0) : ''
sleep 1m | let &l:stl = 'Found '.len(f).' files, finding in '.cwd | redrawstatus
endwhile
catch /^Vim:Interrupt$/
catch
echo "caught" v:exception
endtry
sleep 1m | let &l:stl = sl | redrawstatus
return f
endfunction
function! s:RmDBfiles()
let odbs = split(globpath(s:cscope_vim_dir, "*"), "\n")
for f in odbs
call delete(f)
endfor
endfunction
function! s:FlushIndex()
let lines = []
for d in keys(s:dbs)
call add(lines, d.'|'.s:dbs[d]['id'].'|'.s:dbs[d]['loadtimes'].'|'.s:dbs[d]['dirty'])
endfor
call writefile(lines, s:index_file)
endfunction
function! s:CheckNewFile(dir, newfile)
let id = s:dbs[a:dir]['id']
let cscope_files = s:cscope_vim_dir."/".id.".files"
let files = readfile(cscope_files)
if len(files) > g:cscope_split_threshold
let cscope_files = s:cscope_vim_dir."/".id."_inc.files"
if filereadable(cscope_files)
let files = readfile(cscope_files)
else
let files = []
endif
endif
if count(files, a:newfile) == 0
call add(files, a:newfile)
call writefile(files, cscope_files)
endif
endfunction
function! s:_CreateDB(dir, init)
let id = s:dbs[a:dir]['id']
let cscope_files = s:cscope_vim_dir."/".id."_inc.files"
let cscope_db = s:cscope_vim_dir.'/'.id.'_inc.db'
if ! filereadable(cscope_files) || a:init
let cscope_files = s:cscope_vim_dir."/".id.".files"
let cscope_db = s:cscope_vim_dir.'/'.id.'.db'
if ! filereadable(cscope_files)
let files = <SID>ListFiles(a:dir)
call writefile(files, cscope_files)
endif
endif
exec 'cs kill '.cscope_db
redir @x
exec 'silent !'.g:cscope_cmd.' -b -i '.cscope_files.' -f'.cscope_db
redi END
if @x =~ "\nCommand terminated\n"
echohl WarningMsg | echo "Failed to create cscope database for ".a:dir.", please check if " | echohl None
else
let s:dbs[a:dir]['dirty'] = 0
exec 'cs add '.cscope_db
endif
endfunction
function! s:CheckAbsolutePath(dir, defaultPath)
let d = a:dir
while 1
if !isdirectory(d)
echohl WarningMsg | echo "Please input a valid path." | echohl None
let d = input("", a:defaultPath, 'dir')
elseif (len(d) < 2 || (d[0] != '/' && d[1] != ':'))
echohl WarningMsg | echo "Please input an absolute path." | echohl None
let d = input("", a:defaultPath, 'dir')
else
break
endif
endwhile
let d = substitute(d,'\\','/','g')
let d = substitute(d,'/\+$','','')
return d
endfunction
function! s:InitDB(dir)
let id = localtime()
let s:dbs[a:dir] = {}
let s:dbs[a:dir]['id'] = id
let s:dbs[a:dir]['loadtimes'] = 0
let s:dbs[a:dir]['dirty'] = 0
call <SID>_CreateDB(a:dir, 1)
call <SID>FlushIndex()
endfunction
function! s:LoadDB(dir)
cs kill -1
exe 'cs add '.s:cscope_vim_dir.'/'.s:dbs[a:dir]['id'].'.db'
if filereadable(s:cscope_vim_dir.'/'.s:dbs[a:dir]['id'].'_inc.db')
exe 'cs add '.s:cscope_vim_dir.'/'.s:dbs[a:dir]['id'].'_inc.db'
endif
let s:dbs[a:dir]['loadtimes'] = s:dbs[a:dir]['loadtimes']+1
call <SID>FlushIndex()
endfunction
" 0 -- loaded
" 1 -- cancelled
function! s:AutoloadDB(dir)
let ret = 0
let m_dir = <SID>GetBestPath(a:dir)
if m_dir == ""
echohl WarningMsg | echo "Can not find proper cscope db, please input a path to generate cscope db for." | echohl None
let m_dir = input("", a:dir, 'dir')
if m_dir != ''
let m_dir = <SID>CheckAbsolutePath(m_dir, a:dir)
call <SID>InitDB(m_dir)
call <SID>LoadDB(m_dir)
else
let ret = 1
endif
else
let id = s:dbs[m_dir]['id']
if cscope_connection(2, s:cscope_vim_dir.'/'.id.'.db') == 0
call <SID>LoadDB(m_dir)
endif
endif
return ret
endfunction
function! s:updateDBs(dirs)
for d in a:dirs
call <SID>_CreateDB(d, 0)
endfor
call <SID>FlushIndex()
endfunction
function! s:clearDBs(dir)
cs kill -1
if a:dir == ""
let s:dbs = {}
call <SID>RmDBfiles()
else
let id = s:dbs[a:dir]['id']
call delete(s:cscope_vim_dir."/".id.".files")
call delete(s:cscope_vim_dir.'/'.id.'.db')
call delete(s:cscope_vim_dir."/".id."_inc.files")
call delete(s:cscope_vim_dir.'/'.id.'_inc.db')
unlet s:dbs[a:dir]
endif
call <SID>FlushIndex()
endfunction
function! s:listDBs()
let dirs = keys(s:dbs)
if len(dirs) == 0
echo "You have no cscope dbs now."
else
let s = [' ID LOADTIMES PATH']
for d in dirs
let id = s:dbs[d]['id']
if cscope_connection(2, s:cscope_vim_dir.'/'.id.'.db') == 1
let l = printf("*%d %10d %s", id, s:dbs[d]['loadtimes'], d)
else
let l = printf(" %d %10d %s", id, s:dbs[d]['loadtimes'], d)
endif
call add(s, l)
endfor
echo join(s, "\n")
endif
endfunction
function! s:loadIndex()
let s:dbs = {}
if ! isdirectory(s:cscope_vim_dir)
call mkdir(s:cscope_vim_dir)
elseif filereadable(s:index_file)
let idx = readfile(s:index_file)
for i in idx
let e = split(i, '|')
if len(e) == 0
call delete(s:index_file)
call <SID>RmDBfiles()
else
let db_file = s:cscope_vim_dir.'/'.e[1].'.db'
if filereadable(db_file)
if isdirectory(e[0])
let s:dbs[e[0]] = {}
let s:dbs[e[0]]['id'] = e[1]
let s:dbs[e[0]]['loadtimes'] = e[2]
let s:dbs[e[0]]['dirty'] = (len(e) > 3) ? e[3] :0
else
call delete(db_file)
endif
endif
endif
endfor
else
call <SID>RmDBfiles()
endif
endfunction
function! s:preloadDB()
let dirs = split(g:cscope_preload_path, ';')
for m_dir in dirs
let m_dir = <SID>CheckAbsolutePath(m_dir, m_dir)
if ! has_key(s:dbs, m_dir)
call <SID>InitDB(m_dir)
endif
call <SID>LoadDB(m_dir)
endfor
endfunction
function! CscopeFind(action, word)
let dirtyDirs = []
for d in keys(s:dbs)
if s:dbs[d]['dirty'] == 1
call add(dirtyDirs, d)
endif
endfor
if len(dirtyDirs) > 0
call <SID>updateDBs(dirtyDirs)
endif
let dbl = <SID>AutoloadDB(expand('%:p:h'))
if dbl == 0
try
exe ':lcs f '.a:action.' '.a:word
if g:cscope_open_location == 1
lw
endif
catch
echohl WarningMsg | echo 'Can not find '.a:word.' with querytype as '.a:action.'.' | echohl None
endtry
endif
endfunction
function! CscopeFindInteractive(pat)
call inputsave()
let qt = input("\nChoose a querytype for '".a:pat."'(:help cscope-find)\n c: functions calling this function\n d: functions called by this function\n e: this egrep pattern\n f: this file\n g: this definition\n i: files #including this file\n s: this C symbol\n t: this text string\n\n or\n <querytype><pattern> to query `pattern` instead of '".a:pat."' as `querytype`, Ex. `smain` to query a C symbol named 'main'.\n> ")
call inputrestore()
if len(qt) > 1
call CscopeFind(qt[0], qt[1:])
elseif len(qt) > 0
call CscopeFind(qt, a:pat)
endif
call feedkeys("\<CR>")
endfunction
function! s:onChange()
if expand('%:t') =~? g:cscope_interested_files
let m_dir = <SID>GetBestPath(expand('%:p:h'))
if m_dir != ""
let s:dbs[m_dir]['dirty'] = 1
call <SID>FlushIndex()
call <SID>CheckNewFile(m_dir, expand('%:p'))
redraw
call <SID>echo('Your cscope db will be updated automatically, you can turn off this message by setting g:cscope_silent 1.')
endif
endif
endfunction
function! CscopeUpdateDB()
call <SID>updateDBs(keys(s:dbs))
endfunction
if exists('g:cscope_preload_path')
call <SID>preloadDB()
endif
if g:cscope_auto_update == 1
au BufWritePost * call <SID>onChange()
endif
set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-
function! s:listDirs(A,L,P)
return keys(s:dbs)
endfunction
com! -nargs=? -complete=customlist,<SID>listDirs CscopeClear call <SID>clearDBs("<args>")
com! -nargs=0 CscopeList call <SID>listDBs()
call <SID>loadIndex()