|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 """ |
|
4 Word completion for the eric shell. |
|
5 |
|
6 <h4>NOTE for eric 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 eric |
|
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 |
|
57 class Completer: |
|
58 """ |
|
59 Class implementing the command line completer object. |
|
60 """ |
|
61 |
|
62 def __init__(self, namespace=None): |
|
63 """ |
|
64 Constructor |
|
65 |
|
66 Completer([namespace]) -> completer instance. |
|
67 |
|
68 If unspecified, the default namespace where completions are performed |
|
69 is __main__ (technically, __main__.__dict__). Namespaces should be |
|
70 given as dictionaries. |
|
71 |
|
72 Completer instances should be used as the completion mechanism of |
|
73 readline via the set_completer() call: |
|
74 |
|
75 readline.set_completer(Completer(my_namespace).complete) |
|
76 |
|
77 @param namespace The namespace for the completer. |
|
78 @exception TypeError raised to indicate a wrong data structure of |
|
79 the namespace object |
|
80 """ |
|
81 if namespace and not isinstance(namespace, dict): |
|
82 raise TypeError("namespace must be a dictionary") |
|
83 |
|
84 # Don't bind to namespace quite yet, but flag whether the user wants a |
|
85 # specific namespace or to use __main__.__dict__. This will allow us |
|
86 # to bind to __main__.__dict__ at completion time, not now. |
|
87 if namespace is None: |
|
88 self.use_main_ns = True |
|
89 else: |
|
90 self.use_main_ns = False |
|
91 self.namespace = namespace |
|
92 |
|
93 def complete(self, text, state): |
|
94 """ |
|
95 Public method to return the next possible completion for 'text'. |
|
96 |
|
97 This is called successively with state == 0, 1, 2, ... until it |
|
98 returns None. The completion should begin with 'text'. |
|
99 |
|
100 @param text The text to be completed. (string) |
|
101 @param state The state of the completion. (integer) |
|
102 @return The possible completions as a list of strings. |
|
103 """ |
|
104 if self.use_main_ns: |
|
105 self.namespace = __main__.__dict__ |
|
106 |
|
107 if state == 0: |
|
108 if "." in text: |
|
109 self.matches = self.attr_matches(text) |
|
110 else: |
|
111 self.matches = self.global_matches(text) |
|
112 try: |
|
113 return self.matches[state] |
|
114 except IndexError: |
|
115 return None |
|
116 |
|
117 def _callable_postfix(self, val, word): |
|
118 """ |
|
119 Protected method to check for a callable. |
|
120 |
|
121 @param val value to check (object) |
|
122 @param word word to ammend (string) |
|
123 @return ammended word (string) |
|
124 """ |
|
125 if callable(val): |
|
126 word += "(" |
|
127 return word |
|
128 |
|
129 def global_matches(self, text): |
|
130 """ |
|
131 Public method to compute matches when text is a simple name. |
|
132 |
|
133 @param text The text to be completed. (string) |
|
134 @return A list of all keywords, built-in functions and names currently |
|
135 defined in self.namespace that match. |
|
136 """ |
|
137 import keyword |
|
138 |
|
139 matches = [] |
|
140 seen = {"__builtins__"} |
|
141 n = len(text) |
|
142 for word in keyword.kwlist: |
|
143 if word[:n] == text: |
|
144 seen.add(word) |
|
145 if word in {"finally", "try"}: |
|
146 word += ":" |
|
147 elif word not in { |
|
148 "False", |
|
149 "None", |
|
150 "True", |
|
151 "break", |
|
152 "continue", |
|
153 "pass", |
|
154 "else", |
|
155 }: |
|
156 word += " " |
|
157 matches.append(word) |
|
158 for nspace in [self.namespace, builtins.__dict__]: |
|
159 for word, val in nspace.items(): |
|
160 if word[:n] == text and word not in seen: |
|
161 seen.add(word) |
|
162 matches.append(self._callable_postfix(val, word)) |
|
163 return matches |
|
164 |
|
165 def attr_matches(self, text): |
|
166 """ |
|
167 Public method to compute matches when text contains a dot. |
|
168 |
|
169 Assuming the text is of the form NAME.NAME....[NAME], and is |
|
170 evaluatable in self.namespace, it will be evaluated and its attributes |
|
171 (as revealed by dir()) are used as possible completions. (For class |
|
172 instances, class members are are also considered.) |
|
173 |
|
174 <b>WARNING</b>: this can still invoke arbitrary C code, if an object |
|
175 with a __getattr__ hook is evaluated. |
|
176 |
|
177 @param text The text to be completed. (string) |
|
178 @return A list of all matches. |
|
179 """ |
|
180 import re |
|
181 |
|
182 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) |
|
183 if not m: |
|
184 return [] |
|
185 expr, attr = m.group(1, 3) |
|
186 try: |
|
187 thisobject = eval(expr, self.namespace) # secok |
|
188 except Exception: |
|
189 return [] |
|
190 |
|
191 # get the content of the object, except __builtins__ |
|
192 words = set(dir(thisobject)) |
|
193 words.discard("__builtins__") |
|
194 |
|
195 if hasattr(object, "__class__"): |
|
196 words.add("__class__") |
|
197 words.update(get_class_members(thisobject.__class__)) |
|
198 matches = [] |
|
199 n = len(attr) |
|
200 if attr == "": |
|
201 noprefix = "_" |
|
202 elif attr == "_": |
|
203 noprefix = "__" |
|
204 else: |
|
205 noprefix = None |
|
206 while True: |
|
207 for word in words: |
|
208 if word[:n] == attr and not (noprefix and word[: n + 1] == noprefix): |
|
209 match = "{0}.{1}".format(expr, word) |
|
210 try: |
|
211 val = getattr(thisobject, word) |
|
212 except Exception: # secok |
|
213 pass # Include even if attribute not set |
|
214 else: |
|
215 match = self._callable_postfix(val, match) |
|
216 matches.append(match) |
|
217 if matches or not noprefix: |
|
218 break |
|
219 noprefix = "__" if noprefix == "_" else None |
|
220 matches.sort() |
|
221 return matches |
|
222 |
|
223 |
|
224 def get_class_members(klass): |
|
225 """ |
|
226 Module function to retrieve the class members. |
|
227 |
|
228 @param klass The class object to be analysed. |
|
229 @return A list of all names defined in the class. |
|
230 """ |
|
231 ret = dir(klass) |
|
232 if hasattr(klass, "__bases__"): |
|
233 for base in klass.__bases__: |
|
234 ret += get_class_members(base) |
|
235 return ret |
|
236 |
|
237 |
|
238 # |
|
239 # eflag: noqa = M111 |