1" File: gtags.vim 2" Author: Tama Communications Corporation 3" Version: 0.6.2 4" Last Modified: 2012 Oct 23 5" 6" Copyright and licence 7" --------------------- 8" Copyright (c) 2004, 2008, 2010, 2011 Tama Communications Corporation 9" 10" This file is part of GNU GLOBAL. 11" 12" This program is free software: you can redistribute it and/or modify 13" it under the terms of the GNU General Public License as published by 14" the Free Software Foundation, either version 3 of the License, or 15" (at your option) any later version. 16" 17" This program is distributed in the hope that it will be useful, 18" but WITHOUT ANY WARRANTY; without even the implied warranty of 19" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20" GNU General Public License for more details. 21" 22" You should have received a copy of the GNU General Public License 23" along with this program. If not, see <http://www.gnu.org/licenses/>. 24" 25" Overview 26" -------- 27" The gtags.vim plug-in script integrates the GNU GLOBAL source code tag system 28" with Vim. About the details, see http://www.gnu.org/software/global/. 29" 30" Installation 31" ------------ 32" Drop the file in your plug-in directory or source it from your vimrc. 33" To use this script, you need the GNU GLOBAL-6.0 or later installed 34" in your machine. 35" 36" Usage 37" ----- 38" First of all, you must execute gtags(1) at the root of source directory 39" to make tag files. Assuming that your source directory is '/var/src', 40" it is necessary to execute the following commands. 41" 42" $ cd /var/src 43" $ gtags 44" 45" And you will find four tag files in the directory. 46" 47" General form of Gtags command is as follows: 48" 49" :Gtags [option] pattern 50" 51" To go to func, you can say 52" 53" :Gtags func 54" 55" Input completion is available. If you forgot function name but recall 56" only some characters of the head, please input them and press <TAB> key. 57" 58" :Gtags fu<TAB> 59" :Gtags func <- Vim will append 'nc'. 60" 61" If you omitted argument, vim ask it like this: 62" 63" Gtags for pattern: <current token> 64" 65" Vim execute `global -x main', parse the output, list located 66" objects in quickfix window and load the first entry. The quickfix 67" windows is like this: 68" 69" gozilla/gozilla.c|200| main(int argc, char **argv) 70" gtags-cscope/gtags-cscope.c|124| main(int argc, char **argv) 71" gtags-parser/asm_scan.c|2056| int main() 72" gtags-parser/gctags.c|157| main(int argc, char **argv) 73" gtags-parser/php.c|2116| int main() 74" gtags/gtags.c|152| main(int argc, char **argv) 75" [Quickfix List] 76" 77" You can go to any entry using quickfix command. 78" 79" :cn' 80" go to the next entry. 81" 82" :cp' 83" go to the previous entry. 84" 85" :ccN' 86" go to the Nth entry. 87" 88" :cl' 89" list all entries. 90" 91" You can see the help of quickfix like this: 92" 93" :h quickfix 94" 95" You can use POSIX regular expression too. It requires more execution time though. 96" 97" :Gtags ^[sg]et_ 98" 99" It will match to both of 'set_value' and 'get_value'. 100" 101" To go to the referenced point of func, add -r option. 102" 103" :Gtags -r func 104" 105" To go to any symbols which are not defined in GTAGS, try this. 106" 107" :Gtags -s func 108" 109" To go to any string other than symbol, try this. 110" 111" :Gtags -g ^[sg]et_ 112" 113" This command accomplishes the same function as grep(1) but is more convenient 114" because it retrieves the entire directory structure. 115" 116" To get list of objects in a file 'main.c', use -f command. 117" 118" :Gtags -f main.c 119" 120" If you are editing `main.c' itself, you can use '%' instead. 121" 122" :Gtags -f % 123" 124" You can browse project files whose path includes specified pattern. 125" For example: 126" 127" :Gtags -P /vm/ <- all files under 'vm' directory. 128" :Gtags -P \.h$ <- all include files. 129" :Gtags -P init <- all paths includes 'init' 130" 131" If you omitted the argument and input only <ENTER> key to the prompt, 132" vim shows list of all files in your project. 133" 134" You can use all options of global(1) except for the -c, -p, -u and 135" all long name options. They are sent to global(1) as is. 136" For example, if you want to ignore case distinctions in pattern. 137" 138" :Gtags -gi paTtern 139" 140" It will match to both of 'PATTERN' and 'pattern'. 141" 142" If you want to search a pattern which starts with a hyphen like '-C' 143" then you can use the -e option like grep(1). 144" 145" :Gtags -ge -C 146" 147" By default, Gtags command search only in source files. If you want to 148" search in both source files and text files, or only in text files then 149" 150" :Gtags -go pattern # both source and text 151" :Gtags -gO pattern # only text file 152" 153" See global(1) for other options. 154" 155" The GtagsCursor command brings you to the definition or reference of 156" the current token. 157" 158" :GtagsCursor 159" 160" If you have the hypertext generated by htags(1) then you can display 161" the same place on mozilla browser. Let's load mozilla and try this: 162" 163" :Gozilla 164" 165" If you want to load vim with all main()s then following command line is useful. 166" 167" % vim '+Gtags main' 168" 169" Also see the chapter of 'vim editor' of the on-line manual of GLOBAL. 170" 171" % info global 172" 173" You can use the suggested key mapping with the following code: 174" 175" [$HOME/.vimrc] 176" let Gtags_Auto_Map = 1 177" 178if exists("loaded_gtags") 179 finish 180endif 181 182" 183" global command name 184" 185let s:global_command = $GTAGSGLOBAL 186if s:global_command == '' 187 let s:global_command = "global" 188endif 189" Open the Gtags output window. Set this variable to zero, to not open 190" the Gtags output window by default. You can open it manually by using 191" the :cwindow command. 192" (This code was drived from 'grep.vim'.) 193if !exists("g:Gtags_OpenQuickfixWindow") 194 let g:Gtags_OpenQuickfixWindow = 1 195endif 196 197if !exists("g:Gtags_VerticalWindow") 198 let g:Gtags_VerticalWindow = 0 199endif 200 201if !exists("g:Gtags_Auto_Map") 202 let Gtags_Auto_Map = 0 203endif 204 205if !exists("Gtags_Auto_Update") 206 let Gtags_Auto_Update = 0 207endif 208 209" -- ctags-x format 210" let Gtags_Result = "ctags-x" 211" let Gtags_Efm = "%*\\S%*\\s%l%\\s%f%\\s%m" 212" 213" -- ctags format 214" let Gtags_Result = "ctags" 215" let Gtags_Efm = "%m\t%f\t%l" 216" 217" Gtags_Use_Tags_Format is obsoleted. 218if exists("g:Gtags_Use_Tags_Format") 219 let g:Gtags_Result = "ctags" 220 let g:Gtags_Efm = "%m\t%f\t%l" 221endif 222if !exists("g:Gtags_Result") 223 let g:Gtags_Result = "ctags-mod" 224endif 225if !exists("g:Gtags_Efm") 226 let g:Gtags_Efm = "%f\t%l\t%m" 227endif 228" Character to use to quote patterns and file names before passing to global. 229" (This code was drived from 'grep.vim'.) 230if !exists("g:Gtags_Shell_Quote_Char") 231 if has("win32") || has("win16") || has("win95") 232 let g:Gtags_Shell_Quote_Char = '"' 233 else 234 let g:Gtags_Shell_Quote_Char = "'" 235 endif 236endif 237if !exists("g:Gtags_Single_Quote_Char") 238 if has("win32") || has("win16") || has("win95") 239 let g:Gtags_Single_Quote_Char = "'" 240 let g:Gtags_Double_Quote_Char = '\"' 241 else 242 let s:sq = "'" 243 let s:dq = '"' 244 let g:Gtags_Single_Quote_Char = s:sq . s:dq . s:sq . s:dq . s:sq 245 let g:Gtags_Double_Quote_Char = '"' 246 endif 247endif 248 249" 250" Display error message. 251" 252function! s:Error(msg) 253 echohl WarningMsg | 254 \ echomsg 'Error: ' . a:msg | 255 \ echohl None 256endfunction 257" 258" Extract pattern or option string. 259" 260function! s:Extract(line, target) 261 let l:option = '' 262 let l:pattern = '' 263 let l:force_pattern = 0 264 let l:length = strlen(a:line) 265 let l:i = 0 266 267 " skip command name. 268 if a:line =~ '^Gtags' 269 let l:i = 5 270 endif 271 while l:i < l:length && a:line[l:i] == ' ' 272 let l:i = l:i + 1 273 endwhile 274 while l:i < l:length 275 if a:line[l:i] == "-" && l:force_pattern == 0 276 let l:i = l:i + 1 277 " Ignore long name option like --help. 278 if l:i < l:length && a:line[l:i] == '-' 279 while l:i < l:length && a:line[l:i] != ' ' 280 let l:i = l:i + 1 281 endwhile 282 else 283 while l:i < l:length && a:line[l:i] != ' ' 284 let l:c = a:line[l:i] 285 let l:option = l:option . l:c 286 let l:i = l:i + 1 287 endwhile 288 if l:c == 'e' 289 let l:force_pattern = 1 290 endif 291 endif 292 else 293 let l:pattern = '' 294 " allow pattern includes blanks. 295 while l:i < l:length 296 if a:line[l:i] == "'" 297 let l:pattern = l:pattern . g:Gtags_Single_Quote_Char 298 elseif a:line[l:i] == '"' 299 let l:pattern = l:pattern . g:Gtags_Double_Quote_Char 300 else 301 let l:pattern = l:pattern . a:line[l:i] 302 endif 303 let l:i = l:i + 1 304 endwhile 305 if a:target == 'pattern' 306 return l:pattern 307 endif 308 endif 309 " Skip blanks. 310 while l:i < l:length && a:line[l:i] == ' ' 311 let l:i = l:i + 1 312 endwhile 313 endwhile 314 if a:target == 'option' 315 return l:option 316 endif 317 return '' 318endfunction 319 320" 321" Trim options to avoid errors. 322" 323function! s:TrimOption(option) 324 let l:option = '' 325 let l:length = strlen(a:option) 326 let l:i = 0 327 328 while l:i < l:length 329 let l:c = a:option[l:i] 330 if l:c !~ '[cenpquv]' 331 let l:option = l:option . l:c 332 endif 333 let l:i = l:i + 1 334 endwhile 335 return l:option 336endfunction 337 338" 339" Execute global and load the result into quickfix window. 340" 341function! s:ExecLoad(option, long_option, pattern) 342 " Execute global(1) command and write the result to a temporary file. 343 let l:isfile = 0 344 let l:option = '' 345 let l:result = '' 346 347 if a:option =~ 'f' 348 let l:isfile = 1 349 if filereadable(a:pattern) == 0 350 call s:Error('File ' . a:pattern . ' not found.') 351 return 352 endif 353 endif 354 if a:long_option != '' 355 let l:option = a:long_option . ' ' 356 endif 357 let l:option = l:option . '--result=' . g:Gtags_Result . ' -q' 358 let l:option = l:option . s:TrimOption(a:option) 359 if l:isfile == 1 360 let l:cmd = s:global_command . ' ' . l:option . ' ' . g:Gtags_Shell_Quote_Char . a:pattern . g:Gtags_Shell_Quote_Char 361 else 362 let l:cmd = s:global_command . ' ' . l:option . 'e ' . g:Gtags_Shell_Quote_Char . a:pattern . g:Gtags_Shell_Quote_Char 363 endif 364 365 let l:result = system(l:cmd) 366 if v:shell_error != 0 367 if v:shell_error != 0 368 if v:shell_error == 2 369 call s:Error('invalid arguments. please use the latest GLOBAL.') 370 elseif v:shell_error == 3 371 call s:Error('GTAGS not found.') 372 else 373 call s:Error('global command failed. command line: ' . l:cmd) 374 endif 375 endif 376 return 377 endif 378 if l:result == '' 379 if l:option =~ 'f' 380 call s:Error('Tag not found in ' . a:pattern . '.') 381 elseif l:option =~ 'P' 382 call s:Error('Path which matches to ' . a:pattern . ' not found.') 383 elseif l:option =~ 'g' 384 call s:Error('Line which matches to ' . a:pattern . ' not found.') 385 else 386 call s:Error('Tag which matches to ' . g:Gtags_Shell_Quote_Char . a:pattern . g:Gtags_Shell_Quote_Char . ' not found.') 387 endif 388 return 389 endif 390 391 " Open the quickfix window 392 if g:Gtags_OpenQuickfixWindow == 1 393 if g:Gtags_VerticalWindow == 1 394 topleft vertical copen 395 else 396 botright copen 397 endif 398 endif 399 " Parse the output of 'global -x or -t' and show in the quickfix window. 400 let l:efm_org = &efm 401 let &efm = g:Gtags_Efm 402 cexpr! l:result 403 let &efm = l:efm_org 404endfunction 405 406" 407" RunGlobal() 408" 409function! s:RunGlobal(line) 410 let l:pattern = s:Extract(a:line, 'pattern') 411 412 if l:pattern == '%' 413 let l:pattern = expand('%') 414 elseif l:pattern == '#' 415 let l:pattern = expand('#') 416 endif 417 let l:option = s:Extract(a:line, 'option') 418 " If no pattern supplied then get it from user. 419 if l:pattern == '' 420 let s:option = l:option 421 if l:option =~ 'f' 422 let l:line = input("Gtags for file: ", expand('%'), 'file') 423 else 424 let l:line = input("Gtags for pattern: ", expand('<cword>'), 'custom,GtagsCandidateCore') 425 endif 426 let l:pattern = s:Extract(l:line, 'pattern') 427 if l:pattern == '' 428 call s:Error('Pattern not specified.') 429 return 430 endif 431 endif 432 call s:ExecLoad(l:option, '', l:pattern) 433endfunction 434 435" 436" Execute RunGlobal() depending on the current position. 437" 438function! s:GtagsCursor() 439 let l:pattern = expand("<cword>") 440 let l:option = "--from-here=\"" . line('.') . ":" . expand("%") . "\"" 441 call s:ExecLoad('', l:option, l:pattern) 442endfunction 443 444" 445" Show the current position on mozilla. 446" (You need to execute htags(1) in your source directory.) 447" 448function! s:Gozilla() 449 let l:lineno = line('.') 450 let l:filename = expand("%") 451 let l:result = system('gozilla +' . l:lineno . ' ' . l:filename) 452endfunction 453" 454" Auto update of tag files using incremental update facility. 455" 456function! s:GtagsAutoUpdate() 457 let l:result = system(s:global_command . " -u --single-update=\"" . expand("%") . "\"") 458endfunction 459 460" 461" Custom completion. 462" 463function! GtagsCandidate(lead, line, pos) 464 let s:option = s:Extract(a:line, 'option') 465 return GtagsCandidateCore(a:lead, a:line, a:pos) 466endfunction 467 468function! GtagsCandidateCore(lead, line, pos) 469 if s:option == 'g' 470 return '' 471 elseif s:option == 'f' 472 if isdirectory(a:lead) 473 if a:lead =~ '/$' 474 let l:pattern = a:lead . '*' 475 else 476 let l:pattern = a:lead . '/*' 477 endif 478 else 479 let l:pattern = a:lead . '*' 480 endif 481 return glob(l:pattern) 482 else 483 return system(s:global_command . ' ' . '-c' . s:option . ' ' . a:lead) 484 endif 485endfunction 486 487" Define the set of Gtags commands 488command! -nargs=* -complete=custom,GtagsCandidate Gtags call s:RunGlobal(<q-args>) 489command! -nargs=0 GtagsCursor call s:GtagsCursor() 490command! -nargs=0 Gozilla call s:Gozilla() 491command! -nargs=0 GtagsUpdate call s:GtagsAutoUpdate() 492if g:Gtags_Auto_Update == 1 493 :autocmd! BufWritePost * call s:GtagsAutoUpdate() 494endif 495" Suggested map: 496if g:Gtags_Auto_Map == 1 497 :nmap <F2> :copen<CR> 498 :nmap <F4> :cclose<CR> 499 :nmap <F5> :Gtags<SPACE> 500 :nmap <F6> :Gtags -f %<CR> 501 :nmap <F7> :GtagsCursor<CR> 502 :nmap <F8> :Gozilla<CR> 503 :nmap <C-n> :cn<CR> 504 :nmap <C-p> :cp<CR> 505 :nmap <C-\><C-]> :GtagsCursor<CR> 506endif 507let loaded_gtags = 1 508