" File: gtags.vim
" Author: Tama Communications Corporation
" Version: 0.2
" Last Modified: Apr 8, 2004
"
" Copyright and lisence
" ---------------------
" Copyright (c) 2004 Tama Communications Corporation
"
" This file is part of GNU GLOBAL.
"
" This program is free software: you can redistribute it and/or modify
" it under the terms of the GNU General Public License as published by
" the Free Software Foundation, either version 3 of the License, or
" (at your option) any later version.
"
" This program is distributed in the hope that it will be useful,
" but WITHOUT ANY WARRANTY; without even the implied warranty of
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
" GNU General Public License for more details.
"
" You should have received a copy of the GNU General Public License
" along with this program. If not, see .
"
" Overview
" --------
" The gtags.vim plugin script integrates the GNU GLOBAL source code tag system
" with Vim. About the details, see http://www.gnu.org/software/global/.
"
" Installation
" ------------
" Drop the file in your plugin directory or source it from your vimrc.
" To use this script, you need the GNU GLOBAL installed in your machine.
"
" Usage
" -----
" First of all, you must execute gtags(1) at the root of source directory
" to make tag files. Assuming that your source directory is '/var/src',
" it is neccessary to execute the following command.
"
" $ cd /var/src
" $ gtags -v <- The -v means verbose mode.
"
" And you will find four tag files in the directory.
"
" To go to func, you can say
"
" :Gtags func
"
" Input completion is available. If you forgot function name but recall
" only some characters of the head, please input them and press key.
"
" :Gtags fu
" :Gtags func <- Vim will append 'nc'.
"
" If you omitted argument, vim ask it like this:
"
" Gtags for pattern:
"
" Vim execute `global -t main', parse the output, list located
" objects in quickfix window and load the first entry. The quickfix
" windows is like this:
"
" gctags/gctags.c|119| main
" global/global.c|154| main
" gozilla/gozilla.c|156| main
" gtags/gtags.c|199| main
" libglibc/getopt.c|701| main
" libglibc/getopt1.c|93| main
" [Error List]
"
" You can go to any entry using quickfix command.
"
" :cn'
" go to the next entry.
"
" :cp'
" go to the previous entry.
"
" :ccN'
" go to the N'th entry.
"
" :cl'
" list all entries.
"
" You can see the help of quickfix like this:
"
" :h quickfix
"
" Suggested map:
" map :cn
" map :cp
"
" You can use POSIX regular expression too. It requires more execution time though.
"
" :Gtags ^[sg]et_
"
" It will match to both of 'set_value' and 'get_value'.
"
" To go to the referenced point of func, add -r option.
"
" :Gtags -r func
"
" To go to any symbols which are not defined in GTAGS, try this.
"
" :Gtags -s func
"
" To go to any strings other than symbols, try this.
"
" :Gtags -g ^[sg]et_
"
" This facility utilize grep(1).
"
" To get list of objects in a file 'main.c', use -f command.
"
" :Gtags -f main.c
"
" If you are editing `main.c' itself, you can use '%' instead.
"
" :Gtags -f %
"
" You can browse project files whose path includes specified pattern.
" For example:
"
" :Gtags -P /vm/ <- all files under 'vm' directory.
" :Gtags -P \.h$ <- all include files.
" :Gtags -P init <- all paths includes 'init'
"
" If you omitted the argument and input only 'ENTER' to prompt, vim
" shows list of all files in your project.
"
" You can use all options of global(1) except for the -c, -p, -u and
" all long name options. They are sent to global(1) as is.
" For example, if you want to ignore case distinctions in pattern.
"
" :Gtags -gi paTtern
"
" It will match to both of 'PATTERN' and 'pattern'.
" See global(1) for other options.
"
" The GtagsCursor command brings you to the definition or reference of
" the current token in C language.
"
" :GtagsCursor
"
" The GtagsCursor is not perfect though is considerably wise.
"
" Suggested map:
" map :GtagsCursor
"
" If you have the hypertext generated by htags(1) then you can display
" the same place on mozilla browser. Let's load mozilla and try this:
"
" :Gozilla
"
" Suggested map:
" map :Gozilla
"
" If you want to load vim with all main()s then following command line is useful.
"
" % vim '+Gtags main'
"
" Also see the chapter of 'vim editor' of the online manual of GLOBAL.
"
" % info global
"
if exists("loaded_gtags") || &cp
finish
endif
let loaded_gtags = 1
" Open the Gtags output window. Set this variable to zero, to not open
" the Gtags output window by default. You can open it manually by using
" the :cwindow command.
" (This code was drived from 'grep.vim'.)
if !exists("Gtags_OpenQuickfixWindow")
let Gtags_OpenQuickfixWindow = 1
endif
" Character to use to quote patterns and filenames before passing to global.
" (This code was drived from 'grep.vim'.)
if !exists("Gtags_Shell_Quote_Char")
if has("win32") || has("win16") || has("win95")
let Gtags_Shell_Quote_Char = ''
else
let Gtags_Shell_Quote_Char = "'"
endif
endif
"
" Display error message.
"
function s:Error(msg)
echohl WarningMsg |
\ echomsg 'Error: ' . a:msg |
\ echohl None
endfunction
"
" Extract pattern or option string.
"
"
function s:Extract(str, target)
let out = ''
let mode = ''
let length = strlen(a:str)
let i = 0
while i < length
let c = a:str[i]
" Decide mode.
if c == ' '
let mode = ''
elseif mode == ''
if c == '-'
" Ignore long name option like --help.
if i + 1 < length && a:str[i + 1] == '-'
let mode = 'ignore'
else
let mode = 'option'
endif
else
let mode = 'pattern'
if a:target == 'pattern'
let out = ''
endif
endif
endif
if a:target == mode
if mode == 'pattern'
if c != ' '
let out = out . c
endif
elseif mode == 'option'
if c !~ '[- cpu]'
let out = out . c
endif
endif
endif
let i = i + 1
endwhile
return out
endfunction
"
" RunGlobal()
"
function! s:RunGlobal(...)
let i = 0
let sep = ' '
let line = ''
while i < a:0
let i = i + 1
if line == ''
let line = a:{i}
else
let line = line . ' ' . a:{i}
endif
endwhile
let pattern = s:Extract(line, 'pattern')
" Replace with path name.
if pattern == '%'
let pattern = expand('%')
elseif pattern == '#'
let pattern = expand('#')
endif
let option = s:Extract(line, 'option')
" If no pattern supplied then get it from user.
if pattern == ''
if option =~ 'P'
return
endif
if option =~ 'f'
let line = input("Gtags for file: ", expand('%'))
elseif option =~ 'P'
let line = input("Gtags for pattern: ", '')
else
let line = input("Gtags for pattern: ", expand(''))
endif
let ret = s:Extract(line, 'pattern')
if ret != ''
let pattern = ret
endif
if option == ''
let ret = s:Extract(line, 'option')
if ret != ''
let option = ret
endif
endif
endif
if option =~ 's' && option =~ 'r'
call s:Error('Both of -s and -r are not allowed.')
return
endif
" Execute global(1) command and write the result to a temporary file.
let tmpfile = tempname()
let pattern = g:Gtags_Shell_Quote_Char . pattern . g:Gtags_Shell_Quote_Char
let cmd = 'global' . sep . '-tq' . option . sep . pattern
let stuff = system(cmd . '>' . tmpfile)
if getfsize(tmpfile) == 0
call s:Error('Pattern ' . pattern . ' not found.')
call delete(tmpfile)
return
endif
if v:shell_error != 0
call s:Error('Pattern ' . pattern . ' not found.')
call delete(tmpfile)
return
endif
" Parse the output of 'global -t'.
let efm_org = &efm
let &efm="%m%\\t%f%\\t%l"
execute "silent! cfile " . tmpfile
let &efm = efm_org
" Open the quickfix window
if g:Gtags_OpenQuickfixWindow == 1
" topleft vertical copen
botright copen
endif
cc
call delete(tmpfile)
endfunction
"
" Execute RunGlobal() depending on the current position.
"
function! s:GtagsCursor()
let col = col('.') - 1
let lnum = line('.')
let line = getline(lnum)
let token = expand("")
let flag = '-s'
let pat = '^' . token . '[ \t]*('
if line =~ pat
let flag = '-r'
else
if matchstr(line, "^[ \t]*[a-zA-Z0-9_][a-zA-Z0-9_]*[ \t]*(", col) != ''
let pat = '^#[ \t]*define[ \t][ \t]*' . token . '('
if line =~ pat
let flag = '-r'
else
let flag = '-x'
endif
endif
endif
call s:RunGlobal(flag, token)
endfunction
"
" Show the current position on mozilla.
" (You need to execute htags(1) in your source direcotry.)
"
function! s:Gozilla()
let lnum = line('.')
let fname = expand("%")
let result = system('gozilla +' . lnum . ' ' . fname)
endfunction
"
" Custom completion.
"
function Candidate(ArgLead, CmdLine, CursorPos)
let option = s:Extract(a:CmdLine, 'option')
if option =~ 'P'
return system('global -P ' . a:ArgLead)
else
return system('global -c ' . a:ArgLead)
endif
endfunction
" Define the set of Gtags commands
command! -nargs=* -complete=custom,Candidate Gtags call s:RunGlobal()
command! -nargs=0 GtagsCursor call s:GtagsCursor()
command! -nargs=0 Gozilla call s:Gozilla()
" Suggested map:
"map :GtagsCursor
"map :Gozilla
"map :cn
"map :cp