1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """ Classes that process tag data to collect information."""
20 from copy import copy
21
22 try:
23
24
25 from kwargs_validator import the_validator as validator
26 except ImportError:
27 from pyctags.kwargs_validator import the_validator as validator
28
30 """ This class definition outlines the basic interface for harvesting classes."""
32 """ Called before any entries are processed with self.feed()."""
33 pass
34
35 - def feed(self, entry):
36 """ Called once per ctags_entry.
37 @param entry: a tag entry to process.
38 @type entry: ctags_entry
39 """
40 pass
41
43 """ Called after all ctags_entry instances are processed with self.feed()."""
44 pass
45
47 """ Used to retrieve derived-class specific harvested data."""
48 pass
49
51 """
52 Allows processing of a list of ctags_entry instances without an associated ctags_file.
53 @param taglist: list of ctags_entry instances
54 @type taglist: list
55 """
56 self.do_before()
57 for tag in taglist:
58 self.feed(tag)
59 self.do_after()
60
62 """ Harvests exuberant ctags' extended "kind" information, such as class, member, variable, etc."""
65
66 - def feed(self, entry):
67 """
68 Organizes data into a dict with kind as the keys, values are a list of entries of that kind.
69 @param entry: entry to process
70 @type entry: ctags_entry
71 """
72 if 'kind' in entry.extensions:
73
74 entkey = entry.extensions['kind']
75 if entkey not in self.kinds:
76 self.kinds[entkey] = list()
77 self.kinds[entkey].append(entry)
78
80 """
81 Gets the dict built with self.feed().
82 Dict keys are tag kinds, values are lists of ctags_entry instances sporting that kind.
83 @returns: tag data organized by exuberant ctags kind
84 @rtype: dict
85 """
86 return self.kinds
87
89 """ Organizes tags by name."""
92
93 - def feed(self, entry):
94 """
95 Builds a ctags_entry.name keyed dict.
96 """
97 if entry.name not in self.names:
98 self.names[entry.name] = list()
99 self.names[entry.name].append(entry)
100
102 """
103 Gets the name-organized data.
104 @returns: entries organized with entry.name as key, value is a list of ctags_entry instances that correspond to entry.name
105 @rtype: dict
106 """
107 return self.names
108
110 """ Builds a sorted list of unique tag names."""
112 self.__unique_names = dict()
113 self.__sorted_names = list()
114 self.__name_index = dict()
115
117 """ Number of unique tag names found."""
118 return len(self.__sorted_names)
119
120 - def feed(self, entry):
121 """ Records unique names.
122 @param entry: the entry to collect the name from.
123 @type entry: ctags_entry
124 """
125
126 self.__unique_names[entry.name] = None
127
129 """ Process the unique names into a form easier to query."""
130 self.__sorted_names = list(self.__unique_names.keys())
131 self.__sorted_names.sort()
132
133 i = 0
134 prev_char = self.__sorted_names[0][0]
135 self.__name_index[prev_char] = {'first' : 0}
136 for f in self.__sorted_names:
137 if f[0] not in self.__name_index:
138 self.__name_index[prev_char]['last'] = i - 1
139 self.__name_index[f[0]] = {'first' : i}
140 prev_char = f[0]
141 i += 1
142 self.__name_index[prev_char]['last'] = i
143
145 """
146 Fetches an alphabetical list of unique tag names that begin with matchstr.
147 - B{Parameters:}
148 - B{matchstr:} (str) string to search for in tags db
149 - B{Keyword Arguments:}
150 - B{num_results:} (int) maximum number of results to return, 0 for all, default
151 - B{case_sensitive:} (bool) whether to match case, default False
152 @returns: matching tag names
153 @rtype: list
154 """
155
156 valid_kwargs = ['num_results', 'case_sensitive']
157 validator.validate(kwargs.keys(), valid_kwargs)
158
159 final_list = []
160 case_sensitive = False
161 num_results = 0
162
163 if 'num_results' in kwargs:
164 num_results = int(kwargs['num_results'])
165
166 if len(matchstr) == 0:
167 if num_results:
168 return self.__sorted_names[0:num_results]
169 return self.__sorted_names[:]
170
171 if 'case_sensitive' in kwargs:
172 if kwargs['case_sensitive']:
173 case_sensitive = True
174
175 tag_names_that_start_with_char = []
176
177 if case_sensitive:
178 if matchstr[0] not in self.__name_index:
179 return []
180 else:
181 if matchstr[0].lower() not in self.__name_index and matchstr[0].upper() not in self.__name_index:
182 return []
183
184 if case_sensitive:
185 idxs = self.__name_index[matchstr[0]]
186
187 if idxs['first'] == idxs['last'] + 1:
188 tag_names_that_start_with_char = self.__sorted_names[idxs['first']]
189 else:
190 tag_names_that_start_with_char = self.__sorted_names[idxs['first']:idxs['last'] + 1]
191
192 else:
193 if matchstr[0].lower() in self.__name_index:
194 idxs = self.__name_index[matchstr[0].lower()]
195
196 if idxs['first'] == idxs['last'] + 1:
197 tag_names_that_start_with_char = self.__sorted_names[idxs['first']]
198 else:
199 tag_names_that_start_with_char = self.__sorted_names[idxs['first']:idxs['last'] + 1]
200
201 if matchstr[0].upper() in self.__name_index:
202 idxs = self.__name_index[matchstr[0].upper()]
203
204 if idxs['first'] == idxs['last'] + 1:
205 tag_names_that_start_with_char += [self.__sorted_names[idxs['first']]]
206 else:
207 tag_names_that_start_with_char += self.__sorted_names[idxs['first']:idxs['last'] + 1]
208
209 if len(matchstr) == 1:
210 if num_results == 0:
211 return tag_names_that_start_with_char[:]
212 else:
213 return tag_names_that_start_with_char[0:num_results]
214
215 if case_sensitive:
216 for t in tag_names_that_start_with_char:
217 if (t.find(matchstr) == 0):
218 final_list.append(copy(t))
219 if num_results > 0 and len(final_list) == num_results:
220 return final_list
221 else:
222 for t in tag_names_that_start_with_char:
223 if (t.lower().find(matchstr.lower()) == 0):
224 final_list.append(copy(t))
225 if num_results > 0 and len(final_list) == num_results:
226 return final_list
227
228 return final_list
229