1 " Vim plug-in
  2 " Author: Peter Odding <peter@peterodding.com>
  3 " Last Change: September 6, 2010
  4 " URL: http://peterodding.com/code/vim/easytags/
  5 " Requires: Exuberant Ctags (http://ctags.sf.net)
  6 " License: MIT
  7 " Version: 2.1.7
  8 
  9 " Support for automatic update using the GLVS plug-in.
 10 " GetLatestVimScripts: 3114 1 :AutoInstall: easytags.zip
 11 
 12 " Don't source the plug-in when its already been loaded or &compatible is set.
 13 if &cp || exists('g:loaded_easytags')
 14   finish
 15 endif
 16 
 17 let s:script = expand('<sfile>:p:~')
 18 
 19 " Configuration defaults and initialization. {{{1
 20 
 21 if !exists('g:easytags_file')
 22   if has('win32') || has('win64')
 23     let g:easytags_file = '~\_vimtags'
 24   else
 25     let g:easytags_file = '~/.vimtags'
 26   endif
 27 endif
 28 
 29 if !exists('g:easytags_resolve_links')
 30   let g:easytags_resolve_links = 0
 31 endif
 32 
 33 if !exists('g:easytags_always_enabled')
 34   let g:easytags_always_enabled = 0
 35 endif
 36 
 37 if !exists('g:easytags_on_cursorhold')
 38   let g:easytags_on_cursorhold = 1
 39 endif
 40 
 41 if !exists('g:easytags_ignored_filetypes')
 42   let g:easytags_ignored_filetypes = '^tex$'
 43 endif
 44 
 45 if !exists('g:easytags_autorecurse')
 46   let g:easytags_autorecurse = 0
 47 endif
 48 
 49 if !exists('g:easytags_include_members')
 50   let g:easytags_include_members = 0
 51 endif
 52 
 53 function! s:InitEasyTags(version)
 54   " Check that the location of Exuberant Ctags has been configured or that the
 55   " correct version of the program exists in one of its default locations.
 56   if exists('g:easytags_cmd') && s:CheckCtags(g:easytags_cmd, a:version)
 57     return 1
 58   endif
 59   " On Ubuntu Linux, Exuberant Ctags is installed as `ctags'. On Debian Linux,
 60   " Exuberant Ctags is installed as `exuberant-ctags'. On Free-BSD, Exuberant
 61   " Ctags is installed as `exctags'.
 62   for name in ['ctags', 'exuberant-ctags', 'exctags']
 63     if s:CheckCtags(name, a:version)
 64       let g:easytags_cmd = name
 65       return 1
 66     endif
 67   endfor
 68 endfunction
 69 
 70 function! s:CheckCtags(name, version)
 71   " Not every executable out there named `ctags' is in fact Exuberant Ctags.
 72   " This function makes sure it is because the easytags plug-in requires the
 73   " --list-languages option.
 74   if executable(a:name)
 75     let command = a:name . ' --version'
 76     try
 77       let listing = join(xolox#shell#execute(command, 1), '\n')
 78     catch /^Vim\%((\a\+)\)\=:E117/
 79       " Ignore missing shell.vim plug-in.
 80       let listing = system(command)
 81     catch
 82       " xolox#shell#execute() converts shell errors to exceptions and since
 83       " we're checking whether one of several executables exists we don't want
 84       " to throw an error when the first one doesn't!
 85       return
 86     endtry
 87     let pattern = 'Exuberant Ctags \zs\d\+\(\.\d\+\)*'
 88     let g:easytags_ctags_version = matchstr(listing, pattern)
 89     return s:VersionToNumber(g:easytags_ctags_version) >= a:version
 90   endif
 91 endfunction
 92 
 93 function! s:VersionToNumber(s)
 94   let values = split(a:s, '\.')
 95   if len(values) == 1
 96     return values[0] * 10
 97   elseif len(values) >= 2
 98     return values[0] * 10 + values[1][0]
 99   endif
100 endfunction
101 
102 if !s:InitEasyTags(55)
103   if !exists('g:easytags_ctags_version') || empty(g:easytags_ctags_version)
104     let s:msg = "%s: Plug-in not loaded because Exuberant Ctags isn't installed!"
105     if executable('apt-get')
106       let s:msg .= " On Ubuntu & Debian you can install Exuberant Ctags by"
107       let s:msg .= " installing the package named `exuberant-ctags':"
108       let s:msg .= " sudo apt-get install exuberant-ctags"
109     else
110       let s:msg .= " Please download & install Exuberant Ctags from http://ctags.sf.net"
111     endif
112     echomsg printf(s:msg, s:script)
113   else
114     let s:msg = "%s: Plug-in not loaded because Exuberant Ctags 5.5"
115     let s:msg .= " or newer is required while you have version %s installed!"
116     echomsg printf(s:msg, s:script, g:easytags_ctags_version)
117   endif
118   unlet s:msg
119   finish
120 endif
121 
122 function! s:RegisterTagsFile()
123   " Parse the &tags option and get a list of all tags files *including
124   " non-existing files* (this is why we can't just call tagfiles()).
125   let tagfiles = xolox#option#split_tags(&tags)
126   let expanded = map(copy(tagfiles), 'resolve(expand(v:val))')
127   " Add the filename to the &tags option when the user hasn't done so already.
128   if index(expanded, resolve(expand(g:easytags_file))) == -1
129     " This is a real mess because of bugs in Vim?! :let &tags = '...' doesn't
130     " work on UNIX and Windows, :set tags=... doesn't work on Windows. What I
131     " mean with "doesn't work" is that tagfiles() == [] after the :let/:set
132     " command even though the tags file exists! One easy way to confirm that
133     " this is a bug in Vim is to type :set tags= then press <Tab> followed by
134     " <CR>. Now you entered the exact same value that the code below also did
135     " but suddenly Vim sees the tags file and tagfiles() != [] :-S
136     call insert(tagfiles, g:easytags_file)
137     let value = xolox#option#join_tags(tagfiles)
138     let cmd = ':set tags=' . escape(value, '\ ')
139     if has('win32') || has('win64')
140       " TODO How to clear the expression from Vim's status line?
141       call feedkeys(":" . cmd . "|let &ro=&ro\<CR>", 'n')
142     else
143       execute cmd
144     endif
145   endif
146 endfunction
147 
148 " Let Vim know about the global tags file created by this plug-in.
149 call s:RegisterTagsFile()
150 
151 " The :UpdateTags and :HighlightTags commands. {{{1
152 
153 command! -bar -bang -nargs=* -complete=file UpdateTags call easytags#update(0, <q-bang> == '!', [<f-args>])
154 command! -bar HighlightTags call easytags#highlight()
155 
156 " Automatic commands. {{{1
157 
158 augroup PluginEasyTags
159   autocmd!
160   if g:easytags_always_enabled
161     " TODO Also on FocusGained because tags files might be updated externally?
162     autocmd BufReadPost,BufWritePost * call easytags#autoload()
163   endif
164   if g:easytags_on_cursorhold
165     autocmd CursorHold,CursorHoldI * call easytags#autoload()
166     autocmd BufReadPost * unlet! b:easytags_last_highlighted
167   endif
168 augroup END
169 
170 " }}}1
171 
172 " Make sure the plug-in is only loaded once.
173 let g:loaded_easytags = 1
174 
175 " vim: ts=2 sw=2 et