completer.py
8.92 KB
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
###############################################################################
# Name: completer.py #
# Purpose: Autcompleter interface base class. #
# Author: Cody Precord <cprecord@editra.org> #
# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
# License: wxWindows License #
###############################################################################
"""
Base class for autocompletion providers to implement the completion interface.
@summary: Autocompleter base class
"""
__author__ = "Cody Precord <cprecord@editra.org>"
__svnid__ = "$Id: completer.py 70211 2011-12-31 02:23:54Z CJP $"
__revision__ = "$Revision: 70211 $"
__all__ = [ 'TYPE_FUNCTION', 'TYPE_METHOD', 'TYPE_CLASS', 'TYPE_ATTRIBUTE',
'TYPE_VARIABLE', 'TYPE_ELEMENT', 'TYPE_PROPERTY', 'TYPE_UNKNOWN',
'BaseCompleter', 'Symbol', 'CreateSymbols' ]
#--------------------------------------------------------------------------#
# Imports
import wx
#--------------------------------------------------------------------------#
# Image Type Ids
TYPE_FUNCTION, \
TYPE_METHOD, \
TYPE_CLASS, \
TYPE_ATTRIBUTE, \
TYPE_PROPERTY, \
TYPE_VARIABLE, \
TYPE_ELEMENT, \
TYPE_UNKNOWN = range(1, 9)
#--------------------------------------------------------------------------#
class Symbol(object):
""" Defines a symbol as parsed by the autocompleter.
Symbols with the same name and different type are EQUAL
Symbol hash is based on symbol NAME
"""
# we create lots of these so use slots as a performance tweak
__slots__ = ('_name', '_type')
def __init__(self, name, symtype):
""" Constructor
@param name: Symbol name
@param symtype: Symbol type, one of the TYPE_FUNCTION ... TYPE_UNKNOWN range
"""
super(Symbol, self).__init__()
# Attributes
self._name = unicode(name)
self._type = symtype
def __eq__(self, other):
return (self.Name == other.Name)
def __lt__(self, other):
return (self.Name < other.Name)
def __le__(self, other):
return (self.Name <= other.Name)
def __ne__(self, other):
return (self.Name != other.Name)
def __gt__(self, other):
return (self.Name > other.Name)
def __ge__(self, other):
return (self.Name >= other.Name)
# TODO: this task should probably be delegated to the ui
def __str__(self):
if self.Type != TYPE_UNKNOWN:
return u'?'.join([self.Name, unicode(self.Type)])
else:
return self.Name
def __hash__(self):
return hash(self.Name)
Name = property(lambda self: self._name,
lambda self, n: setattr(self, '_name', n))
Type = property(lambda self: self._type,
lambda self, t: setattr(self, '_type', t))
#--------------------------------------------------------------------------#
def CreateSymbols(arglst, symtype=TYPE_UNKNOWN):
"""Convert a list of strings to a list of Symbol objects
@param arglst: list of strings
@keyword symtype: TYPE_FOO
@return: list of Symbols
"""
return [ Symbol(obj, symtype) for obj in arglst ]
#--------------------------------------------------------------------------#
class BaseCompleter(object):
"""Base Autocomp provider class"""
def __init__(self, parent):
"""Initializes the auto-completion service
@param parent: parent of this service object
"""
super(BaseCompleter, self).__init__()
# Attributes
self._buffer = parent
self._log = wx.GetApp().GetLog()
self._case_sensitive = False
self._autocomp_after = False
self._choose_single = True
self._autocomp_keys = list()
self._autocomp_stop = u''
self._autocomp_fillup = u''
self._calltip_keys = list()
self._calltip_cancel = list()
#--- Override in subclass ----#
def GetAutoCompList(self, command):
"""Retrieves the sorted autocomplete list for a command
@param command: command string to do lookup on
@return: list of strings
"""
return list()
def GetCallTip(self, command):
"""Returns the calltip string for a command
@param command: command to get calltip for (string)
@return: string
"""
return u''
def OnCompletionInserted(self, pos, text):
"""Called by the buffer when an autocomp selection has been inserted.
The completer can override this method to
@param pos: Position the caret was at before the insertion
@param text: text that was inserted at pos
"""
pass
#--- End override in subclass ----#
def GetCommandString(self, stc, line, col):
"""Get the command string found at the current location to use
for lookups.
@param stc: EditraStc
@param line: line text
@param col: position in line (column)
"""
line = line.expandtabs(stc.GetTabWidth())
line = line[:col]
if line and ord(line[-1]) in (self.GetAutoCompKeys() + self.GetCallTipKeys()):
line = line[:-1]
cmd_lmt = list(self.GetAutoCompStops() + self.GetAutoCompFillups())
for key in self.GetAutoCompKeys():
kval = unichr(key)
if kval in cmd_lmt:
cmd_lmt.remove(kval)
cmd = u''
curr_pos = len(line) - 1
while curr_pos > -1:
cmd = line[curr_pos:]
if len(cmd) and cmd[0] not in cmd_lmt:
curr_pos -= 1
else:
break
for char in cmd_lmt:
cmd = cmd.replace(char, u'')
return cmd.strip()
def GetAutoCompKeys(self):
"""Returns the list of key codes for activating the auto-completion.
@return: list of characters used for activating auto-completion
"""
return self._autocomp_keys
def SetAutoCompKeys(self, key_list):
"""Set the keys to provide completions on
@param key_list: List of key codes
"""
self._autocomp_keys = key_list
def GetAutoCompStops(self):
"""Returns a string of characters that should cancel
the auto-completion lookup.
@return: string of characters that will hide the autocomp/calltip
"""
return self._autocomp_stop
def SetAutoCompStops(self, stops):
"""Set the keys to cancel auto-completions on.
@param stops: string
"""
self._autocomp_stop = stops
def GetAutoCompFillups(self):
"""Get the list of characters to do a fillup on
@return: string
"""
return self._autocomp_fillup
def SetAutoCompFillups(self, fillups):
"""Set the list of characters to do a fillup on
@param fillups: string
"""
self._autocomp_fillup = fillups
def GetCallTipKeys(self):
"""Returns the list of keys to activate a calltip on
@return: list of calltip activation keys
"""
return self._calltip_keys
def SetCallTipKeys(self, keys):
"""Set the list of keys to activate calltips on
@return: list of calltip activation keys
"""
self._calltip_keys = keys
def GetCallTipCancel(self):
"""Get the list of key codes that should stop a calltip"""
return self._calltip_cancel
def SetCallTipCancel(self, key_list):
"""Set the list of key codes that should stop a calltip"""
self._calltip_cancel = key_list
def GetBuffer(self):
"""Get the reference to the buffer this autocomp object is owned by
@return: EditraStc
"""
return self._buffer
def GetCaseSensitive(self):
"""Are commands case sensitive or not
@return: bool
"""
return self._case_sensitive
def SetCaseSensitive(self, sensitive):
"""Set whether this completer is case sensitive or not
@param sensitive: bool
"""
self._case_sensitive = sensitive
def GetChooseSingle(self):
"""Get whether the completer should automatically choose a selection
when there is only one symbol in the completion list.
@return: bool
"""
return self._choose_single
def SetChooseSingle(self, single):
"""Set whether the completer should automatically choose a selection
when there is only one symbol in the completion list.
@param single: bool
"""
self._choose_single = single
def ShouldCheck(self, cpos):
"""Should completions be attempted
@param cpos: current buffer position
@return: bool
"""
buff = self.GetBuffer()
rval = True
if buff is not None:
if buff.IsString(cpos) or buff.IsComment(cpos):
rval = False
return rval