DebugClients/Python3/FlexCompleter.py

changeset 0
de9c2efb9d02
child 15
f6ccc31d6e72
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 """
4 Word completion for the eric4 shell
5
6 <h4>NOTE for eric4 variant</h4>
7
8 This version is a re-implementation of rlcompleter
9 as found in the Python3 library. It is modified to work with the eric4
10 debug clients.
11
12 <h4>Original rlcompleter documentation</h4>
13
14 This requires the latest extension to the readline module. The completer
15 completes keywords, built-ins and globals in a selectable namespace (which
16 defaults to __main__); when completing NAME.NAME..., it evaluates (!) the
17 expression up to the last dot and completes its attributes.
18
19 It's very cool to do "import sys" type "sys.", hit the
20 completion key (twice), and see the list of names defined by the
21 sys module!
22
23 Tip: to use the tab key as the completion key, call
24
25 readline.parse_and_bind("tab: complete")
26
27 <b>Notes</b>:
28 <ul>
29 <li>
30 Exceptions raised by the completer function are *ignored* (and
31 generally cause the completion to fail). This is a feature -- since
32 readline sets the tty device in raw (or cbreak) mode, printing a
33 traceback wouldn't work well without some complicated hoopla to save,
34 reset and restore the tty state.
35 </li>
36 <li>
37 The evaluation of the NAME.NAME... form may cause arbitrary
38 application defined code to be executed if an object with a
39 __getattr__ hook is found. Since it is the responsibility of the
40 application (or the user) to enable this feature, I consider this an
41 acceptable risk. More complicated expressions (e.g. function calls or
42 indexing operations) are *not* evaluated.
43 </li>
44 <li>
45 When the original stdin is not a tty device, GNU readline is never
46 used, and this module (and the readline module) are silently inactive.
47 </li>
48 </ul>
49 """
50
51 import builtins
52 import __main__
53
54 __all__ = ["Completer"]
55
56 class Completer(object):
57 """
58 Class implementing the command line completer object.
59 """
60 def __init__(self, namespace = None):
61 """
62 Create a new completer for the command line.
63
64 Completer([namespace]) -> completer instance.
65
66 If unspecified, the default namespace where completions are performed
67 is __main__ (technically, __main__.__dict__). Namespaces should be
68 given as dictionaries.
69
70 Completer instances should be used as the completion mechanism of
71 readline via the set_completer() call:
72
73 readline.set_completer(Completer(my_namespace).complete)
74
75 @param namespace The namespace for the completer.
76 """
77
78 if namespace and type(namespace) != type({}):
79 raise TypeError('namespace must be a dictionary')
80
81 # Don't bind to namespace quite yet, but flag whether the user wants a
82 # specific namespace or to use __main__.__dict__. This will allow us
83 # to bind to __main__.__dict__ at completion time, not now.
84 if namespace is None:
85 self.use_main_ns = True
86 else:
87 self.use_main_ns = False
88 self.namespace = namespace
89
90 def complete(self, text, state):
91 """
92 Return the next possible completion for 'text'.
93
94 This is called successively with state == 0, 1, 2, ... until it
95 returns None. The completion should begin with 'text'.
96
97 @param text The text to be completed. (string)
98 @param state The state of the completion. (integer)
99 @return The possible completions as a list of strings.
100 """
101 if self.use_main_ns:
102 self.namespace = __main__.__dict__
103
104 if state == 0:
105 if "." in text:
106 self.matches = self.attr_matches(text)
107 else:
108 self.matches = self.global_matches(text)
109 try:
110 return self.matches[state]
111 except IndexError:
112 return None
113
114 def _callable_postfix(self, val, word):
115 """
116 Protected method to check for a callable.
117
118 @param val value to check (object)
119 @param word word to ammend (string)
120 @return ammended word (string)
121 """
122 if hasattr(val, '__call__'):
123 word = word + "("
124 return word
125
126 def global_matches(self, text):
127 """
128 Compute matches when text is a simple name.
129
130 @param text The text to be completed. (string)
131 @return A list of all keywords, built-in functions and names currently
132 defined in self.namespace that match.
133 """
134 import keyword
135 matches = []
136 n = len(text)
137 for word in keyword.kwlist:
138 if word[:n] == text:
139 matches.append(word)
140 for nspace in [builtins.__dict__, self.namespace]:
141 for word, val in nspace.items():
142 if word[:n] == text and word != "__builtins__":
143 matches.append(self._callable_postfix(val, word))
144 return matches
145
146 def attr_matches(self, text):
147 """
148 Compute matches when text contains a dot.
149
150 Assuming the text is of the form NAME.NAME....[NAME], and is
151 evaluatable in self.namespace, it will be evaluated and its attributes
152 (as revealed by dir()) are used as possible completions. (For class
153 instances, class members are are also considered.)
154
155 <b>WARNING</b>: this can still invoke arbitrary C code, if an object
156 with a __getattr__ hook is evaluated.
157
158 @param text The text to be completed. (string)
159 @return A list of all matches.
160 """
161 import re
162
163 # Another option, seems to work great. Catches things like ''.<tab>
164 m = re.match(r"(\S+(\.\w+)*)\.(\w*)", text)
165
166 if not m:
167 return
168 expr, attr = m.group(1, 3)
169 try:
170 thisobject = eval(expr, self.namespace)
171 except Exception:
172 return []
173
174 # get the content of the object, except __builtins__
175 words = dir(thisobject)
176 if "__builtins__" in words:
177 words.remove("__builtins__")
178
179 if hasattr(object,'__class__'):
180 words.append('__class__')
181 words = words + get_class_members(object.__class__)
182 matches = []
183 n = len(attr)
184 for word in words:
185 try:
186 if word[:n] == attr and hasattr(thisobject, word):
187 val = getattr(thisobject, word)
188 word = self._callable_postfix(val, "{0}.{1}".format(expr, word))
189 matches.append(word)
190 except:
191 # some badly behaved objects pollute dir() with non-strings,
192 # which cause the completion to fail. This way we skip the
193 # bad entries and can still continue processing the others.
194 pass
195 return matches
196
197 def get_class_members(klass):
198 """
199 Module function to retrieve the class members.
200
201 @param klass The class object to be analysed.
202 @return A list of all names defined in the class.
203 """
204 ret = dir(klass)
205 if hasattr(klass, '__bases__'):
206 for base in klass.__bases__:
207 ret = ret + get_class_members(base)
208 return ret

eric ide

mercurial