summaryrefslogtreecommitdiff
path: root/.vim/plugin/autotag.vim
blob: 8bb2d0e9667c1af5d2abf5054104e0c6a56cffaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
" This file supplies automatic tag regeneration when saving files
" There's a problem with ctags when run with -a (append)
" ctags doesn't remove entries for the supplied source file that no longer exist
" so this script (implemented in python) finds a tags file for the file vim has
" just saved, removes all entries for that source file and *then* runs ctags -a

if has("python")

python << EEOOFF
import os
import string
import os.path
import fileinput
import sys
import vim

def echo(str):
   str=str.replace('\\', '\\\\')
   str=str.replace('"', "'")
   vim.command("redraw | echo \"%s\"" % str)

class AutoTag:
   def __init__(self, excludesuffix="", ctags_cmd="ctags", verbose=0):
      self.tags = {}
      self.excludesuffix = [ "." + s for s in excludesuffix.split(".") ]
      verbose = long(verbose)
      if verbose > 0:
         self.verbose = verbose
      else:
         self.verbose = 0
      self.sep_used_by_ctags = '/'
      self.cwd = os.getcwd()
      self.ctags_cmd = ctags_cmd
      self.count = 0

   def findTagFile(self, source):
      ( drive, file ) = os.path.splitdrive(source)
      while file:
         file = os.path.dirname(file)
         tagsFile = os.path.join(drive, file, "tags")
         self.diag(2, "does %s exist?", tagsFile)
         if os.path.isfile(tagsFile):
            self.diag(2, "Found tags file %s", tagsFile)
            return tagsFile
         elif not file or file == os.sep or file == "//" or file == "\\\\":
            self.diag(2, "exhausted search for tag file for %s", source)
            return None
         self.diag(2, "Nope. :-| %s does NOT exist", tagsFile)
      return None

   def addSource(self, source):
      if not source:
         return
      if os.path.splitext(source)[1] in self.excludesuffix:
         self.diag(1, "Ignoring excluded file " + source)
         return
      tagsFile = self.findTagFile(source)
      if tagsFile:
         self.diag(2, "if tagsFile:")
         relativeSource = source[len(os.path.dirname(tagsFile)):]
         self.diag(2, "relativeSource = source[len(os.path.dirname(tagsFile)):]")
         if relativeSource[0] == os.sep:
            self.diag(2, "if relativeSource[0] == os.sep:")
            relativeSource = relativeSource[1:]
            self.diag(2, "relativeSource = relativeSource[1:]")
         if os.sep != self.sep_used_by_ctags:
            self.diag(2, "if os.sep != self.sep_used_by_ctags:")
            relativeSource = string.replace(relativeSource, os.sep, self.sep_used_by_ctags)
            self.diag(2, "relativeSource = string.replace(relativeSource, os.sep, self.sep_used_by_ctags)")
         if self.tags.has_key(tagsFile):
            self.diag(2, "if self.tags.has_key(tagsFile):")
            self.tags[tagsFile].append(relativeSource)
            self.diag(2, "self.tags[tagsFile].append(relativeSource)")
         else:
            self.diag(2, "else:")
            self.tags[tagsFile] = [ relativeSource ]
            self.diag(2, "self.tags[tagsFile] = [ relativeSource ]")

   def stripTags(self, tagsFile, sources):
      self.diag(1, "Removing tags for %s from tags file %s", (sources, tagsFile))
      backup = ".SAFE"
      for line in fileinput.input(files=tagsFile, inplace=True, backup=backup):
         if line[-1:] == '\n':
            line = line[:-1]
         if line[-1:] == '\r':
            line = line[:-1]
         if line[0] == "!":
            print line
         else:
            fields = string.split(line, "\t")
            if len(fields) > 3:
               found = False
               for source in sources:
                  if fields[1] == source:
                     found = True
                     break
               if not found:
                  print line
            else:
               print line
      os.unlink(tagsFile + backup)

   def rebuildTagFiles(self):
      for tagsFile in self.tags.keys():
         tagsDir = os.path.dirname(tagsFile)
         sources = self.tags[tagsFile]
         os.chdir(tagsDir)
         self.stripTags(tagsFile, sources)
         cmd = "%s -a " % self.ctags_cmd
         for source in sources:
            if os.path.isfile(source):
               cmd += " '%s'" % source
         self.diag(1, "%s: %s", (tagsDir, cmd))
         (ch_in, ch_out) = os.popen2(cmd)
         for line in ch_out:
            pass
      os.chdir(self.cwd)

   def diag(self, level, msg, args = None):
      if msg and args:
         msg = msg % args
      if level <= self.verbose:
         echo(msg)
EEOOFF

function! AutoTag()
python << EEOOFF
at = AutoTag(vim.eval("g:autotagExcludeSuffixes"), vim.eval("g:autotagCtagsCmd"), long(vim.eval("g:autotagVerbosityLevel")))
at.addSource(vim.eval("expand(\"%:p\")"))
at.rebuildTagFiles()
EEOOFF
endfunction

if !exists("g:autotagVerbosityLevel")
   let g:autotagVerbosityLevel=0
endif
if !exists("g:autotagExcludeSuffixes")
   let g:autotagExcludeSuffixes="tml.xml"
endif
if !exists("g:autotagCtagsCmd")
   let g:autotagCtagsCmd="ctags"
endif
if !exists("g:autotag_autocmd_set")
   let g:autotag_autocmd_set=1
   autocmd BufWritePost,FileWritePost * call AutoTag ()
endif

endif " has("python")

" vim:sw=3:ts=3