Skip to content

Commit

Permalink
Version 2.0: Initial upload
Browse files Browse the repository at this point in the history
  • Loading branch information
ghgary authored and vim-scripts committed Oct 18, 2010
0 parents commit ecc69df
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
29 changes: 29 additions & 0 deletions README
@@ -0,0 +1,29 @@
This is a mirror of http://www.vim.org/scripts/script.php?script_id=610

This is a new version of Alexey Marinichev&#039s ctags.vim script, vimscript #12. I have modified it with the author&#039s permission, but cannot upload it as a new version of the original script because Vim Online now allows only the original author to do that.

The original script used exuberant ctags to build a list of tags for the current file and displayed the name of the function the cursor was in (actually the name of the tag at or above the cursor&#039s line) in the title bar.

This version has been modified to display the function/tag name in the status line instead of or in addtion to the title bar. If multiple windows are open, the correct function/tag name is displayed in each status line. The script has also been modified to be a plugin instead of having to be sourced. Finally, since exuberant ctags now supports Python and Vim languages as well as C, .py and .vim were added to the list of suffixes that automatically start the script.

New in Version 2.1
------------------

1. Keith Reynolds contributed some changes that have made a dramatic improvement in the startup time when opening large files containing many tags. The improvement is greatest when using a vim compiled with Perl support. His changes also result in this version using less memory than version 2.0.

2. Keith also added automatic enabling of the status line (i.e., setting 'statusline' to 2) when entering a buffer in which the script is active.

3. The default g:ctags_args value has been changed to use C and vim type values more appropriate for this plugin. If you prefer the previous defaults, the values are still noted in the script and can be used instead by setting them yourself in your ~/.vimrc.

4. The default g:ctags_path value has been changed to be better for most users. This can also be reverted to the previous default value by looking in the script for the previous setting and putting this in your ~/.vimrc.

5. The ctags database is now regenerated every time a buffer is saved. This keeps the database up to date as a file is changed. If this is a performance problem for you, just add

let g:ctags_regenerate = 0

to your ~/.vimrc.

6. The behavior of the cursor when moving vertically through text has been improved. It no longer "forgets" the column to which it was last set as often. It may forget now only when the tag name changes.

7. Configuration varaibles may now be set at any time, not just at vim startup time.

209 changes: 209 additions & 0 deletions plugin/ctags.vim
@@ -0,0 +1,209 @@
" ctags.vim: Display function name in the title bar and/or status line.
" Author: Alexey Marinichev <lyosha-vim@lyosha.no-ip.org>
" Contributor: Gary Johnson <garyjohn@spk.agilent.com>
" Last Change: 2003-04-02 21:22:14
" Version: 2.0
" URL: http://vim.sourceforge.net/scripts/script.php?script_id=12

" DETAILED DESCRIPTION:
" This script uses exuberant ctags to build the list of tags for the current
" file. CursorHold event is then used to update titlestring and/or statusline.
"
" Upon sourcing an autocommand is created with event type CursorHold. It
" updates the title string or a buffer-local variable using the function
" GetTagName. Another autocommand of type BufEnter is created to generate
" tags for *.c, *.cpp, *.h, *.py and *.vim files.
"
" Function GenerateTags builds an array of tag names.
"
" Function GetTagName takes line number argument and returns the tag name.
"
" Function SetStatusline sets the value of 'statusline'.
"
" Function TagName returns the cached tag name.
"
" INSTALL DETAILS:
" Before sourcing the script do:
" let g:ctags_path='/path/to/ctags'
" let g:ctags_args='-I __declspec+'
" (or whatever other additional arguments you want to pass to ctags)
" let g:ctags_title=1 " To show tag name in title bar.
" let g:ctags_statusline=1 " To show tag name in status line.
" let generate_tags=1 " To start automatically when a supported
" " file is opened.
" :CTAGS command starts the script.

" Exit quickly when already loaded.
"
if exists("loaded_ctags")
finish
endif
let loaded_ctags = 1

" Allow the use of line-continuation, even if user has 'compatible' set.
"
let s:save_cpo = &cpo
set cpo&vim

if !exists("ctags_path")
"let g:ctags_path='ctags'
"let g:ctags_args=''
let g:ctags_path=$VIM.'/ctags/ctags'
let g:ctags_args='-I __declspec+'
endif

" If user doesn't specify either g:ctags_title or g:ctags_statusline,
" revert to the original behavior, which was equivalent to g:ctags_title.
"
if !exists("g:ctags_title") && !exists("g:ctags_statusline")
let g:ctags_title=1
endif

command! CTAGS let generate_tags=1|call GenerateTags()

autocmd BufEnter *.c,*.cpp,*.h,*.py,*.vim
\ if exists('generate_tags')
\ && !exists('b:lines')
\ && filereadable(expand("<afile>"))
\ | call GenerateTags()
\ | endif

set updatetime=500

if exists("g:ctags_title")
autocmd CursorHold *
\ if exists('generate_tags')
\ | let &titlestring='%t%( %M%)%( (%{expand("%:~:.:h")})%)%( %a%)%='.GetTagName(line("."))
\ | endif
endif

if exists("g:ctags_statusline")
autocmd CursorHold *
\ if exists('generate_tags')
\ | call s:SetStatusline()
\ | endif
endif

"set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)%=%(tag:\ %-{GetTagName(line("."))}%)



"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" No changes should be reqired below (unless there are bugs).
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

if version < 600
function! Stridx(haysack, needle)
return match(a:haysack, a:needle)
endfunction
else
function! Stridx(haysack, needle)
return stridx(a:haysack, a:needle)
endfunction
endif

let g:ctags_obligatory_args = '-n --sort=no -o -'
let g:ctags_pattern="^\\(.\\{-}\\)\t.\\{-}\t\\(\\d*\\).*"

" This function builds an array of tag names. b:lines contains line numbers;
" b:l<number> is the tag value for the line <number>.
function! GenerateTags()
let ctags = system(g:ctags_path.' '.g:ctags_args.' '.g:ctags_obligatory_args.' "'.expand('%').'"')

" b:length is one greater than the length of maximum line number.
let b:length = 8
let b:lines = ''

" strlen(spaces) must be at least b:length.
let spaces = ' '
let i = 1
let len = strlen(ctags)

while strlen(ctags) > 0
let one_tag = strpart(ctags, 0, Stridx(ctags, "\n"))
let tag_name = substitute(one_tag, g:ctags_pattern, '\1', '')
let tag_line_number = substitute(one_tag, g:ctags_pattern, '\2', '')
execute "let b:l".tag_line_number . " = '".tag_name."'"
let b:lines = strpart(b:lines.tag_line_number.spaces, 0, b:length*i)
let i = i+1

" vim 5.x insists that strpart takes 3 arguments.
let ctags = strpart(ctags, Stridx(ctags, "\n")+1, len)
endwhile

let b:lines = b:lines."9999999"
endfunction

" This function returns the tag name for given index.
function! GetLine(i)
return strpart(b:lines, a:i*b:length, b:length)+0
endfunction

" This function does binary search in the array of tag names and returns
" corresponding tag.
function! GetTagName(curline)
if !exists("b:lines")
return ""
endif

let left = 0
let right = strlen(b:lines)/b:length

if a:curline < GetLine(left)
return ""
endif

while left<right
let middle = (right+left+1)/2
let middleline = GetLine(middle)

if middleline == a:curline
let left = middle
break
endif

if middleline > a:curline
let right = middle-1
else
let left = middle
endif
endwhile

exe "let ret=b:l".GetLine(left)
return ret
endfunction

" This function sets the value of 'statusline'.
function! s:SetStatusline()
let w:tag_name = GetTagName(line("."))
if &ruler
let &statusline='%<%f %(%h%m%r %)%=%{TagName()} %-15.15(%l,%c%V%)%P'
" Equivalent to default status
" line with 'ruler' set:
"
" '%<%f %h%m%r%=%-15.15(%l,%c%V%)%P'
else
let &statusline='%<%f %(%h%m%r %)%=%{TagName()}'
endif
" The %(%) pair around the "%h%m%r "
" is there to suppress the extra
" space between the file name and
" the function name when those
" elements are null.
endfunction

" This function returns the value of w:tag_name if it exists, otherwise
" ''.
function! TagName()
if exists('w:tag_name')
return w:tag_name
else
return ''
endif
endfunction

" Restore cpo.
let &cpo= s:save_cpo
unlet s:save_cpo

" vim:set ts=8 sts=4 sw=4:

0 comments on commit ecc69df

Please sign in to comment.