Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 262 lines (232 sloc) 8.287 kB
da20fc0 @AndrewRadev Updates to plugins
authored
1 " Increment the number below for a dynamic #include guard
2 let s:autotag_vim_version=1
3
4 if exists("g:autotag_vim_version_sourced")
5 if s:autotag_vim_version == g:autotag_vim_version_sourced
6 finish
7 endif
8 endif
9
10 let g:autotag_vim_version_sourced=s:autotag_vim_version
11
de197b0 @AndrewRadev Some powerful scripts
authored
12 " This file supplies automatic tag regeneration when saving files
13 " There's a problem with ctags when run with -a (append)
14 " ctags doesn't remove entries for the supplied source file that no longer exist
15 " so this script (implemented in python) finds a tags file for the file vim has
16 " just saved, removes all entries for that source file and *then* runs ctags -a
17
18 if has("python")
19 python << EEOOFF
20 import os
21 import string
22 import os.path
23 import fileinput
24 import sys
25 import vim
26 import time
f20b798 @AndrewRadev Autotag update
authored
27 import logging
28
29 # global vim config variables used (all are g:autotag<name>):
30 # name purpose
31 # maxTagsFileSize a cap on what size tag file to strip etc
32 # ExcludeSuffixes suffixes to not ctags on
33 # VerbosityLevel logging verbosity (as in Python logging module)
34 # CtagsCmd name of ctags command
35 # TagsFile name of tags file to look for
36 # Disabled Disable autotag (enable by setting to any non-blank value)
37 # StopAt stop looking for a tags file (and make one) at this directory (defaults to $HOME)
38 vim_global_defaults = dict(maxTagsFileSize = 1024*1024*7,
39 ExcludeSuffixes = "tml.xml.text.txt",
40 VerbosityLevel = logging.WARNING,
41 CtagsCmd = "ctags",
42 TagsFile = "tags",
43 Disabled = 0,
44 StopAt = 0)
de197b0 @AndrewRadev Some powerful scripts
authored
45
46 # Just in case the ViM build you're using doesn't have subprocess
47 if sys.version < '2.4':
48 def do_cmd(cmd, cwd):
49 old_cwd=os.getcwd()
50 os.chdir(cwd)
51 (ch_in, ch_out) = os.popen2(cmd)
52 for line in ch_out:
53 pass
54 os.chdir(old_cwd)
55
56 import traceback
57 def format_exc():
58 return ''.join(traceback.format_exception(*list(sys.exc_info())))
59
60 else:
61 import subprocess
62 def do_cmd(cmd, cwd):
63 p = subprocess.Popen(cmd, shell=True, stdout=None, stderr=None, cwd=cwd)
64
65 from traceback import format_exc
66
f20b798 @AndrewRadev Autotag update
authored
67 def vim_global(name, kind = string):
68 ret = vim_global_defaults.get(name, None)
69 try:
70 v = "g:autotag%s" % name
71 exists = (vim.eval("exists('%s')" % v) == "1")
72 if exists:
73 ret = vim.eval(v)
74 else:
75 if isinstance(ret, int):
76 vim.command("let %s=%s" % (v, ret))
77 else:
78 vim.command("let %s=\"%s\"" % (v, ret))
79 finally:
80 if kind == bool:
81 ret = (ret not in [0, "0"])
82 elif kind == int:
83 ret = int(ret)
84 elif kind == string:
85 pass
86 return ret
87
88 class VimAppendHandler(logging.Handler):
89 def __init__(self, name):
90 logging.Handler.__init__(self)
91 self.__name = name
92 self.__formatter = logging.Formatter()
93
94 def __findBuffer(self):
95 for b in vim.buffers:
96 if b and b.name and b.name.endswith(self.__name):
97 return b
98
99 def emit(self, record):
100 b = self.__findBuffer()
101 if b:
102 b.append(self.__formatter.format(record))
103
104 def makeAndAddHandler(logger, name):
105 ret = VimAppendHandler(name)
106 logger.addHandler(ret)
107 return ret
108
de197b0 @AndrewRadev Some powerful scripts
authored
109
110 class AutoTag:
f20b798 @AndrewRadev Autotag update
authored
111 MAXTAGSFILESIZE = long(vim_global("maxTagsFileSize"))
112 DEBUG_NAME = "autotag_debug"
113 LOGGER = logging.getLogger(DEBUG_NAME)
114 HANDLER = makeAndAddHandler(LOGGER, DEBUG_NAME)
115
116 @staticmethod
117 def setVerbosity():
118 try:
119 level = int(vim_global("VerbosityLevel"))
120 except:
121 level = vim_global_defaults["VerbosityLevel"]
122 AutoTag.LOGGER.setLevel(level)
de197b0 @AndrewRadev Some powerful scripts
authored
123
f20b798 @AndrewRadev Autotag update
authored
124 def __init__(self):
de197b0 @AndrewRadev Some powerful scripts
authored
125 self.tags = {}
f20b798 @AndrewRadev Autotag update
authored
126 self.excludesuffix = [ "." + s for s in vim_global("ExcludeSuffixes").split(".") ]
127 AutoTag.setVerbosity()
de197b0 @AndrewRadev Some powerful scripts
authored
128 self.sep_used_by_ctags = '/'
f20b798 @AndrewRadev Autotag update
authored
129 self.ctags_cmd = vim_global("CtagsCmd")
130 self.tags_file = str(vim_global("TagsFile"))
de197b0 @AndrewRadev Some powerful scripts
authored
131 self.count = 0
f20b798 @AndrewRadev Autotag update
authored
132 self.stop_at = vim_global("StopAt")
de197b0 @AndrewRadev Some powerful scripts
authored
133
134 def findTagFile(self, source):
f20b798 @AndrewRadev Autotag update
authored
135 AutoTag.LOGGER.info('source = "%s"', source)
de197b0 @AndrewRadev Some powerful scripts
authored
136 ( drive, file ) = os.path.splitdrive(source)
137 while file:
138 file = os.path.dirname(file)
f20b798 @AndrewRadev Autotag update
authored
139 AutoTag.LOGGER.info('drive = "%s", file = "%s"', drive, file)
140 tagsDir = os.path.join(drive, file)
141 tagsFile = os.path.join(tagsDir, self.tags_file)
142 AutoTag.LOGGER.info('tagsFile "%s"', tagsFile)
de197b0 @AndrewRadev Some powerful scripts
authored
143 if os.path.isfile(tagsFile):
144 st = os.stat(tagsFile)
145 if st:
146 size = getattr(st, 'st_size', None)
da20fc0 @AndrewRadev Updates to plugins
authored
147 if size is None:
f20b798 @AndrewRadev Autotag update
authored
148 AutoTag.LOGGER.warn("Could not stat tags file %s", tagsFile)
de197b0 @AndrewRadev Some powerful scripts
authored
149 return None
f20b798 @AndrewRadev Autotag update
authored
150 if size > AutoTag.MAXTAGSFILESIZE:
151 AutoTag.LOGGER.info("Ignoring too big tags file %s", tagsFile)
de197b0 @AndrewRadev Some powerful scripts
authored
152 return None
153 return tagsFile
f20b798 @AndrewRadev Autotag update
authored
154 elif tagsDir and tagsDir == self.stop_at:
155 AutoTag.LOGGER.info("Reached %s. Making one %s" % (self.stop_at, tagsFile))
156 open(tagsFile, 'wb').close()
157 return tagsFile
de197b0 @AndrewRadev Some powerful scripts
authored
158 elif not file or file == os.sep or file == "//" or file == "\\\\":
f20b798 @AndrewRadev Autotag update
authored
159 AutoTag.LOGGER.info('bail (file = "%s")' % (file, ))
de197b0 @AndrewRadev Some powerful scripts
authored
160 return None
161 return None
162
163 def addSource(self, source):
164 if not source:
f20b798 @AndrewRadev Autotag update
authored
165 AutoTag.LOGGER.warn('No source')
de197b0 @AndrewRadev Some powerful scripts
authored
166 return
167 if os.path.basename(source) == self.tags_file:
f20b798 @AndrewRadev Autotag update
authored
168 AutoTag.LOGGER.info("Ignoring tags file %s", self.tags_file)
de197b0 @AndrewRadev Some powerful scripts
authored
169 return
170 (base, suff) = os.path.splitext(source)
171 if suff in self.excludesuffix:
f20b798 @AndrewRadev Autotag update
authored
172 AutoTag.LOGGER.info("Ignoring excluded suffix %s for file %s", source, suff)
de197b0 @AndrewRadev Some powerful scripts
authored
173 return
174 tagsFile = self.findTagFile(source)
175 if tagsFile:
176 relativeSource = source[len(os.path.dirname(tagsFile)):]
177 if relativeSource[0] == os.sep:
178 relativeSource = relativeSource[1:]
179 if os.sep != self.sep_used_by_ctags:
180 relativeSource = string.replace(relativeSource, os.sep, self.sep_used_by_ctags)
181 if self.tags.has_key(tagsFile):
182 self.tags[tagsFile].append(relativeSource)
183 else:
184 self.tags[tagsFile] = [ relativeSource ]
185
f20b798 @AndrewRadev Autotag update
authored
186 def goodTag(self, line, excluded):
187 if line[0] == '!':
188 return True
189 else:
190 f = string.split(line, '\t')
191 AutoTag.LOGGER.log(1, "read tags line:%s", str(f))
192 if len(f) > 3 and f[1] not in excluded:
193 return True
194 return False
195
de197b0 @AndrewRadev Some powerful scripts
authored
196 def stripTags(self, tagsFile, sources):
f20b798 @AndrewRadev Autotag update
authored
197 AutoTag.LOGGER.info("Stripping tags for %s from tags file %s", ",".join(sources), tagsFile)
de197b0 @AndrewRadev Some powerful scripts
authored
198 backup = ".SAFE"
f20b798 @AndrewRadev Autotag update
authored
199 input = fileinput.FileInput(files=tagsFile, inplace=True, backup=backup)
200 try:
201 for l in input:
202 l = l.strip()
203 if self.goodTag(l, sources):
204 print l
205 finally:
206 input.close()
207 try:
208 os.unlink(tagsFile + backup)
209 except StandardError:
210 pass
de197b0 @AndrewRadev Some powerful scripts
authored
211
212 def updateTagsFile(self, tagsFile, sources):
213 tagsDir = os.path.dirname(tagsFile)
214 self.stripTags(tagsFile, sources)
215 if self.tags_file:
216 cmd = "%s -f %s -a " % (self.ctags_cmd, self.tags_file)
217 else:
218 cmd = "%s -a " % (self.ctags_cmd,)
219 for source in sources:
220 if os.path.isfile(os.path.join(tagsDir, source)):
221 cmd += " '%s'" % source
f20b798 @AndrewRadev Autotag update
authored
222 AutoTag.LOGGER.log(1, "%s: %s", tagsDir, cmd)
de197b0 @AndrewRadev Some powerful scripts
authored
223 do_cmd(cmd, tagsDir)
224
225 def rebuildTagFiles(self):
226 for (tagsFile, sources) in self.tags.items():
227 self.updateTagsFile(tagsFile, sources)
228 EEOOFF
229
230 function! AutoTag()
231 python << EEOOFF
232 try:
f20b798 @AndrewRadev Autotag update
authored
233 if not vim_global("Disabled", bool):
234 at = AutoTag()
235 at.addSource(vim.eval("expand(\"%:p\")"))
236 at.rebuildTagFiles()
de197b0 @AndrewRadev Some powerful scripts
authored
237 except:
f20b798 @AndrewRadev Autotag update
authored
238 logging.warning(format_exc())
de197b0 @AndrewRadev Some powerful scripts
authored
239 EEOOFF
f20b798 @AndrewRadev Autotag update
authored
240 if exists(":TlistUpdate")
241 TlistUpdate
242 endif
243 endfunction
244
245 function! AutoTagDebug()
246 new
247 file autotag_debug
248 setlocal buftype=nowrite
249 setlocal bufhidden=delete
250 setlocal noswapfile
251 normal 
de197b0 @AndrewRadev Some powerful scripts
authored
252 endfunction
253
254 augroup autotag
255 au!
256 autocmd BufWritePost,FileWritePost * call AutoTag ()
257 augroup END
258
259 endif " has("python")
260
da20fc0 @AndrewRadev Updates to plugins
authored
261 " vim:shiftwidth=3:ts=3
Something went wrong with that request. Please try again.