diff --git a/plugin/gutentags_plus.vim b/plugin/gutentags_plus.vim index 8a8cab7..25c8ccb 100644 --- a/plugin/gutentags_plus.vim +++ b/plugin/gutentags_plus.vim @@ -9,10 +9,12 @@ let s:windows = has('win32') || has('win64') || has('win16') || has('win95') -if v:version >= 800 - set cscopequickfix=s+,c+,d+,i+,t+,e+,g+,f+,a+ -else - set cscopequickfix=s+,c+,d+,i+,t+,e+,g+,f+ +if len(&cscopequickfix) == 0 + if v:version >= 800 + set cscopequickfix=s+,c+,d+,i+,t+,e+,g+,f+,a+ + else + set cscopequickfix=s+,c+,d+,i+,t+,e+,g+,f+ + endif endif let g:gutentags_auto_add_gtags_cscope = 0 @@ -313,15 +315,54 @@ command! -nargs=0 GscopeKill call s:GscopeKill() "---------------------------------------------------------------------- " taglist "---------------------------------------------------------------------- +function! s:global_taglist(pattern) abort + let dbname = s:get_gtags_file() + let root = get(b:, 'gutentags_root', '') + if dbname == '' || root == '' + call s:ErrorMsg("no gtags database for this project, check gutentags's documents") + return 0 + endif + if !filereadable(dbname) + call s:ErrorMsg('gtags database is not ready yet') + return 0 + endif + let pwd = getcwd() + let $GTAGSDBPATH = fnamemodify(dbname, ':p:h') + let $GTAGSROOT = root + let lst = systemlist('global --result=cscope -a "'. a:pattern . '"') + let rsl_list = [] + for li in lst + let tag_info = {} + let tag_info['filename'] = li[:stridx(li, " ") - 1] + let li = li[stridx(li, " ") + 1:] + let tag_info['name'] = li[:stridx(li, " ") - 1] + let li = li[stridx(li, " ") + 1:] + let tag_info['line'] = str2nr(li[:stridx(li, " ") - 1]) + let li = li[stridx(li, " ") + 1:] + let tag_info['cmd'] = '/^' . li . '$/' + let rsl_list = add(rsl_list, tag_info) + endfor + return rsl_list +endfunc + + function! s:taglist(pattern) let ftags = [] try - let ftags = taglist(a:pattern) + if &cscopetag + let ftags = s:global_taglist(a:pattern) + else + let ftags = taglist(a:pattern) + endif catch /^Vim\%((\a\+)\)\=:E/ " if error occured, reset tagbsearch option and try again. let bak = &tagbsearch set notagbsearch - let ftags = taglist(a:pattern) + if &cscopetag + let ftags = s:global_taglist(a:pattern) + else + let ftags = taglist(a:pattern) + endif let &tagbsearch = bak endtry " take care ctags windows filename bug @@ -624,7 +665,86 @@ function! s:FindTags(bang, tagname, ...) return 1 endfunc +function! TagFind(tagname) + return s:signature(a:tagname, 0, &ft) +endfunc +"---------------------------------------------------------------------- +" jump to tag +"---------------------------------------------------------------------- +let s:script_dir = fnamemodify(resolve(expand(':p')), ':h') +function s:JumpToTag(tagname) + let tags = map(s:signature(a:tagname, 0, &ft), function('s:colorize_tag')) + let tags_as_string = map(tags, 'join(v:val, " ")') + + if len(tags_as_string) == 0 + echohl WarningMsg + echo 'Tag not found: ' . a:tagname + echohl None + elseif len(tags_as_string) == 1 + if &cscopetag + execute "GscopeAdd" + let old_cscopequickfix = &cscopequickfix + set cscopequickfix=g- + execute 'cstag!' a:tagname + "cclose + let &cscopequickfix=old_cscopequickfix + else + execute 'tag' a:tagname + endif + else + let path = s:script_dir . '/../../fzf.vim/bin/preview.sh' + if filereadable(path) + let preview = 'cmd={3..}; cmd=\${cmd:2:-2}; cmd=\$(echo "\$cmd" | sed -e ''s/[^a-zA-Z0-9 ,_=:]/\\\\&/g''); lineno=\$(rg -n "\$cmd" {2} | cut -d: -f1); '. path . ' {2}:\$lineno' + call fzf#run({ + \ 'source': tags_as_string, + \ 'sink': function('s:fzf_sink', [a:tagname]), + \ 'options': '--ansi --tiebreak index --preview-window up:60% --preview "' . preview . '" --prompt " 🔎 \"' . a:tagname . '\"> "', + \ }) + else + " TODO: fill the quickfix window with tags + endif + endif +endfunc +function! s:fzf_sink(identifier, selection) + let l:count = split(a:selection)[0] + if &cscopetag + execute "GscopeAdd" + let old_cscopequickfix=&cscopequickfix + set cscopequickfix=g- + execute 'cstag!' a:identifier + execute 'cc' l:count + let &cscopequickfix=old_cscopequickfix + else + execute l:count . 'tag' a:identifier + endif +endfunction + +function! s:colorize_tag(index, tag_dict) + let components = [a:index + 1] + if has_key(a:tag_dict, 'filename') + call add(components, s:magenta(fnamemodify(a:tag_dict['filename'], ":~:."))) + endif + if has_key(a:tag_dict, 'class') + call add(components, s:green(a:tag_dict['class'])) + endif + if has_key(a:tag_dict, 'cmd') + call add(components, s:red(a:tag_dict['cmd'])) + endif + return components +endfunction + +function! s:green(s) + return "\033[32m" . a:s . "\033[m" +endfunction + +function! s:magenta(s) + return "\033[35m" . a:s . "\033[m" +endfunction + +function! s:red(s) + return "\033[31m" . a:s . "\033[m" +endfunction "---------------------------------------------------------------------- " setup keymaps "---------------------------------------------------------------------- @@ -649,6 +769,7 @@ nnoremap GscopeFindFile FindCwordCmd('GscopeFin nnoremap GscopeFindInclude FindCwordCmd('GscopeFind i', 1) nnoremap GscopeFindAssign FindCwordCmd('GscopeFind a', 0) nnoremap GscopeFindCtag FindCwordCmd('GscopeFind z', 0) +nnoremap GscopeJumpToTag :call JumpToTag(expand('')) if get(g:, 'gutentags_plus_nomap', 0) == 0 nmap cs GscopeFindSymbol @@ -662,4 +783,5 @@ if get(g:, 'gutentags_plus_nomap', 0) == 0 nmap ca GscopeFindAssign nmap cz GscopeFindCtag nmap ck :GscopeKill + nmap GscopeJumpToTag endif