DebugClients/Python2/FlexCompleter.py

branch
jsonrpc
changeset 5133
b7fe69c6cb1c
parent 4833
803bf753032a
equal deleted inserted replaced
5132:a094eee9f862 5133:b7fe69c6cb1c
1 # -*- coding: utf-8 -*-
2
3 """
4 Word completion for the eric6 shell.
5
6 <h4>NOTE for eric6 variant</h4>
7
8 This version is a re-implementation of FlexCompleter
9 as found in the PyQwt package. It is modified to work with the eric6 debug
10 clients.
11
12
13 <h4>NOTE for the PyQwt variant</h4>
14
15 This version is a re-implementation of FlexCompleter
16 with readline support for PyQt&sip-3.6 and earlier.
17
18 Full readline support is present in PyQt&sip-snapshot-20030531 and later.
19
20
21 <h4>NOTE for FlexCompleter</h4>
22
23 This version is a re-implementation of rlcompleter with
24 selectable namespace.
25
26 The problem with rlcompleter is that it's hardwired to work with
27 __main__.__dict__, and in some cases one may have 'sandboxed' namespaces.
28 So this class is a ripoff of rlcompleter, with the namespace to work in as
29 an optional parameter.
30
31 This class can be used just like rlcompleter, but the Completer class now
32 has a constructor with the optional 'namespace' parameter.
33
34 A patch has been submitted to Python@sourceforge for these changes to go in
35 the standard Python distribution.
36
37
38 <h4>Original rlcompleter documentation</h4>
39
40 This requires the latest extension to the readline module (the
41 completes keywords, built-ins and globals in __main__; when completing
42 NAME.NAME..., it evaluates (!) the expression up to the last dot and
43 completes its attributes.
44
45 It's very cool to do "import string" type "string.", hit the
46 completion key (twice), and see the list of names defined by the
47 string module!
48
49 Tip: to use the tab key as the completion key, call
50
51 'readline.parse_and_bind("tab: complete")'
52
53 <b>Notes</b>:
54 <ul>
55 <li>
56 Exceptions raised by the completer function are *ignored* (and
57 generally cause the completion to fail). This is a feature -- since
58 readline sets the tty device in raw (or cbreak) mode, printing a
59 traceback wouldn't work well without some complicated hoopla to save,
60 reset and restore the tty state.
61 </li>
62 <li>
63 The evaluation of the NAME.NAME... form may cause arbitrary
64 application defined code to be executed if an object with a
65 __getattr__ hook is found. Since it is the responsibility of the
66 application (or the user) to enable this feature, I consider this an
67 acceptable risk. More complicated expressions (e.g. function calls or
68 indexing operations) are *not* evaluated.
69 </li>
70 <li>
71 GNU readline is also used by the built-in functions input() and
72 raw_input(), and thus these also benefit/suffer from the completer
73 features. Clearly an interactive application can benefit by
74 specifying its own completer function and using raw_input() for all
75 its input.
76 </li>
77 <li>
78 When the original stdin is not a tty device, GNU readline is never
79 used, and this module (and the readline module) are silently inactive.
80 </li>
81 </ul>
82 """
83
84 #*****************************************************************************
85 #
86 # Since this file is essentially a minimally modified copy of the rlcompleter
87 # module which is part of the standard Python distribution, I assume that the
88 # proper procedure is to maintain its copyright as belonging to the Python
89 # Software Foundation:
90 #
91 # Copyright (C) 2001 Python Software Foundation, www.python.org
92 #
93 # Distributed under the terms of the Python Software Foundation license.
94 #
95 # Full text available at:
96 #
97 # http://www.python.org/2.1/license.html
98 #
99 #*****************************************************************************
100
101 import __builtin__
102 import __main__
103
104 __all__ = ["Completer"]
105
106
107 class Completer(object):
108 """
109 Class implementing the command line completer object.
110 """
111 def __init__(self, namespace=None):
112 """
113 Constructor
114
115 Completer([namespace]) -> completer instance.
116
117 If unspecified, the default namespace where completions are performed
118 is __main__ (technically, __main__.__dict__). Namespaces should be
119 given as dictionaries.
120
121 Completer instances should be used as the completion mechanism of
122 readline via the set_completer() call:
123
124 readline.set_completer(Completer(my_namespace).complete)
125
126 @param namespace namespace for the completer
127 @exception TypeError raised to indicate a wrong namespace structure
128 """
129 if namespace and not isinstance(namespace, dict):
130 raise TypeError('namespace must be a dictionary')
131
132 # Don't bind to namespace quite yet, but flag whether the user wants a
133 # specific namespace or to use __main__.__dict__. This will allow us
134 # to bind to __main__.__dict__ at completion time, not now.
135 if namespace is None:
136 self.use_main_ns = 1
137 else:
138 self.use_main_ns = 0
139 self.namespace = namespace
140
141 def complete(self, text, state):
142 """
143 Public method to return the next possible completion for 'text'.
144
145 This is called successively with state == 0, 1, 2, ... until it
146 returns None. The completion should begin with 'text'.
147
148 @param text The text to be completed. (string)
149 @param state The state of the completion. (integer)
150 @return The possible completions as a list of strings.
151 """
152 if self.use_main_ns:
153 self.namespace = __main__.__dict__
154
155 if state == 0:
156 if "." in text:
157 self.matches = self.attr_matches(text)
158 else:
159 self.matches = self.global_matches(text)
160 try:
161 return self.matches[state]
162 except IndexError:
163 return None
164
165 def _callable_postfix(self, val, word):
166 """
167 Protected method to check for a callable.
168
169 @param val value to check (object)
170 @param word word to ammend (string)
171 @return ammended word (string)
172 """
173 if hasattr(val, '__call__'):
174 word = word + "("
175 return word
176
177 def global_matches(self, text):
178 """
179 Public method to compute matches when text is a simple name.
180
181 @param text The text to be completed. (string)
182 @return A list of all keywords, built-in functions and names currently
183 defined in self.namespace that match.
184 """
185 import keyword
186 matches = []
187 n = len(text)
188 for word in keyword.kwlist:
189 if word[:n] == text:
190 matches.append(word)
191 for nspace in [__builtin__.__dict__, self.namespace]:
192 for word, val in nspace.items():
193 if word[:n] == text and word != "__builtins__":
194 matches.append(self._callable_postfix(val, word))
195 return matches
196
197 def attr_matches(self, text):
198 """
199 Public method to compute matches when text contains a dot.
200
201 Assuming the text is of the form NAME.NAME....[NAME], and is
202 evaluatable in self.namespace, it will be evaluated and its attributes
203 (as revealed by dir()) are used as possible completions. (For class
204 instances, class members are are also considered.)
205
206 <b>WARNING</b>: this can still invoke arbitrary C code, if an object
207 with a __getattr__ hook is evaluated.
208
209 @param text The text to be completed. (string)
210 @return A list of all matches.
211 """
212 import re
213
214 # Testing. This is the original code:
215 #m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
216
217 # Modified to catch [] in expressions:
218 #m = re.match(r"([\w\[\]]+(\.[\w\[\]]+)*)\.(\w*)", text)
219
220 # Another option, seems to work great. Catches things like ''.<tab>
221 m = re.match(r"(\S+(\.\w+)*)\.(\w*)", text)
222
223 if not m:
224 return
225 expr, attr = m.group(1, 3)
226 try:
227 thisobject = eval(expr, self.namespace)
228 except Exception:
229 return []
230
231 # get the content of the object, except __builtins__
232 words = dir(thisobject)
233 if "__builtins__" in words:
234 words.remove("__builtins__")
235
236 if hasattr(object, '__class__'):
237 words.append('__class__')
238 words = words + get_class_members(object.__class__)
239 matches = []
240 n = len(attr)
241 for word in words:
242 try:
243 if word[:n] == attr and hasattr(thisobject, word):
244 val = getattr(thisobject, word)
245 word = self._callable_postfix(
246 val, "%s.%s" % (expr, word))
247 matches.append(word)
248 except Exception:
249 # some badly behaved objects pollute dir() with non-strings,
250 # which cause the completion to fail. This way we skip the
251 # bad entries and can still continue processing the others.
252 pass
253 return matches
254
255
256 def get_class_members(klass):
257 """
258 Module function to retrieve the class members.
259
260 @param klass The class object to be analysed.
261 @return A list of all names defined in the class.
262 """
263 # PyQwt's hack for PyQt&sip-3.6 and earlier
264 if hasattr(klass, 'getLazyNames'):
265 return klass.getLazyNames()
266 # vanilla Python stuff
267 ret = dir(klass)
268 if hasattr(klass, '__bases__'):
269 for base in klass.__bases__:
270 ret = ret + get_class_members(base)
271 return ret
272
273 #
274 # eflag: FileType = Python2
275 # eflag: noqa = M601, M702, M111

eric ide

mercurial