src/eric7/DebugClients/Python/FlexCompleter.py

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

eric ide

mercurial