-
Notifications
You must be signed in to change notification settings - Fork 19
/
gtags.py
152 lines (117 loc) · 4.65 KB
/
gtags.py
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
151
152
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import platform
import pprint
import re
import shlex
import subprocess
import unittest
import sublime
PP = pprint.PrettyPrinter(indent=4)
TAGS_RE = re.compile(
'(?P<symbol>[^\s]+)\s+'
'(?P<linenum>[^\s]+)\s+'
'(?P<path>[^\s]+)\s+'
'(?P<signature>.*)'
)
ENV_PATH = os.environ['PATH']
IS_WINDOWS = platform.system() == 'Windows'
def find_tags_root(current, previous=None):
current = os.path.normpath(current)
if not os.path.isdir(current):
return None
parent = os.path.dirname(current)
if parent == previous:
return None
if 'GTAGS' in os.listdir(current):
return current
return find_tags_root(parent, current)
class TagSubprocess(object):
def __init__(self, **kwargs):
self.default_kwargs = kwargs
if IS_WINDOWS:
self.default_kwargs['shell'] = True
def create(self, command, **kwargs):
final_kwargs = self.default_kwargs
final_kwargs.update(kwargs)
if int(sublime.version()) >= 3000:
if isinstance(command,str):
command = shlex.split(command)
else:
if isinstance(command, basestring):
command = shlex.split(command.encode('utf-8'))
return subprocess.Popen(command, **final_kwargs)
def stdout(self, command, **kwargs):
process = self.create(command, stdout=subprocess.PIPE, **kwargs)
return process.communicate()[0]
def call(self, command, **kwargs):
process = self.create(command, stderr=subprocess.PIPE, **kwargs)
_, stderr = process.communicate()
return process.returncode, stderr
class TagFile(object):
def _expand_path(self, path):
path = os.path.expandvars(os.path.expanduser(path))
if IS_WINDOWS:
path = path.encode('utf-8')
return path
def __init__(self, root_dir=None, extra_paths=[]):
self.__env = {'PATH': ENV_PATH}
self.__root = root_dir
if root_dir is not None:
self.__env['GTAGSROOT'] = self._expand_path(root_dir)
if extra_paths:
self.__env['GTAGSLIBPATH'] = os.pathsep.join(
map(self._expand_path, extra_paths))
self.subprocess = TagSubprocess(env=self.__env)
def start_with(self, prefix):
if int(sublime.version()) >= 3000:
return self.subprocess.stdout('global -c %s' % prefix).decode("utf-8").splitlines()
else:
return self.subprocess.stdout('global -c %s' % prefix).splitlines()
def _match(self, pattern, options):
if int(sublime.version()) >= 3000:
lines = self.subprocess.stdout(
'global %s %s' % (options, pattern)).decode("utf-8").splitlines()
else:
lines = self.subprocess.stdout(
'global %s %s' % (options, pattern)).splitlines()
matches = []
for search_obj in (t for t in (TAGS_RE.search(l) for l in lines) if t):
matches.append(search_obj.groupdict())
return matches
def match(self, pattern, reference=False):
return self._match(pattern, '-ax' + ('r' if reference else ''))
def rebuild(self):
retcode, stderr = self.subprocess.call('gtags -v', cwd=self.__root)
success = retcode == 0
if not success:
print(stderr)
return success
class GTagsTest(unittest.TestCase):
def test_start_with(self):
f = TagFile('$HOME/repos/work/val/e4/proto1/')
assert len(f.start_with("Exp_Set")) == 4
def test_match(pattern):
f = TagFile('$HOME/repos/work/val/e4/proto1/')
matches = f.match("ExpAddData")
assert len(matches) == 4
assert matches[0]["path"] == "/Users/tabi/Dropbox/repos/work/val/e4/proto1/include/ExpData.h"
assert matches[0]["linenum"] == '1463'
def test_start_with2(self):
f = TagFile()
assert len(f.start_with("Exp_Set")) == 0
def test_reference(self):
f = TagFile('$HOME/repos/work/val/e4/proto1/')
refs = f.match("Exp_IsSkipProgress", reference=True)
assert len(refs) == 22
assert refs[0]["path"] == "/Users/tabi/Dropbox/repos/work/val/e4/proto1/include/ExpPrivate.h"
assert refs[0]["linenum"] == '1270'
def test_extra_paths(self):
f = TagFile("$HOME/tmp/sample", ["$HOME/repos/work/val/e4/proto1/", "~/pkg/llvm-trunk/tools/clang/"])
matches = f.match("InitHeaderSearch")
assert len(matches) == 1
assert matches[0]["path"] == "/Users/tabi/pkg/llvm-trunk/tools/clang/lib/Frontend/InitHeaderSearch.cpp"
assert matches[0]["linenum"] == '44'
if __name__ == '__main__':
unittest.main()