Ticket #19700: patch-Lib-rlcompleter.py.diff
File patch-Lib-rlcompleter.py.diff, 5.1 KB (added by stromnov (Andrey Stromnov), 15 years ago) |
---|
-
Lib/rlcompleter.py
old new 1 1 """Word completion for GNU readline 2.0. 2 2 3 3 This requires the latest extension to the readline module. The completer 4 completes keywords, built-ins and globals in a selectable namespace (which 5 defaults to __main__); when completing NAME.NAME..., it evaluates (!) the 6 expression up to the last dot and completes its attributes. 4 completes keywords, built-ins, globals, and file names in a selectable 5 namespace (which defaults to __main__); when completing NAME.NAME..., 6 it evaluates (!) the expression up to the last dot and completes its 7 attributes. 7 8 8 9 It's very cool to do "import sys" type "sys.", hit the 9 10 completion key (twice), and see the list of names defined by the … … 72 73 self.use_main_ns = 0 73 74 self.namespace = namespace 74 75 76 # The cache of matches for a particular text fragment. 77 self.matches = [] 78 75 79 def complete(self, text, state): 76 80 """Return the next possible completion for 'text'. 77 81 78 82 This is called successively with state == 0, 1, 2, ... until it 79 returns None. The completion should begin with 'text'. 83 returns None. The completion should begin with 'text'. Any text 84 with a period (.) will match as an attribute. Any text that begins 85 with a single or double quote will match using file name expansion. 80 86 81 87 """ 82 88 if self.use_main_ns: 83 89 self.namespace = __main__.__dict__ 84 90 91 # For the first call with this set of text, compute all possible 92 # matches and store them in a member variable. Subsequent calls 93 # will then iterate through this set of matches. 85 94 if state == 0: 86 if "." in text: 95 if ('"' in text) or ("'" in text): 96 self.matches = self.file_matches(text) 97 elif "." in text: 87 98 self.matches = self.attr_matches(text) 88 99 else: 89 100 self.matches = self.global_matches(text) 90 try:101 if state < len(self.matches): 91 102 return self.matches[state] 92 e xcept IndexError:103 else: 93 104 return None 94 105 95 106 def _callable_postfix(self, val, word): … … 129 140 130 141 """ 131 142 import re 143 import types 144 145 # Setup the regular expression for attributes 132 146 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) 133 147 if not m: 134 148 return [] 149 150 # Group 1 is the class name, group 3 is the attribute text 135 151 expr, attr = m.group(1, 3) 136 152 try: 137 153 thisobject = eval(expr, self.namespace) … … 143 159 if "__builtins__" in words: 144 160 words.remove("__builtins__") 145 161 146 if hasattr(thisobject, '__class__'): 147 words.append('__class__') 148 words.extend(get_class_members(thisobject.__class__)) 162 # If this type is a class instance, use the __class__ member to 163 # get the dictionary of attributes 164 if type(thisobject) == types.InstanceType: 165 if hasattr(thisobject, '__class__'): 166 words.append('__class__') 167 words.extend(get_class_members(thisobject.__class__)) 168 elif type(thisobject) == types.ClassType: 169 words.extend(get_class_members(thisobject)) 170 else: 171 words.extend(dir(thisobject)) 172 173 # Build the full matching text from class.attribute matches 149 174 matches = [] 150 175 n = len(attr) 151 176 for word in words: … … 155 180 matches.append(word) 156 181 return matches 157 182 183 def file_matches(self, text): 184 """Compute matches when text is a file name. 185 186 Expects a leading single or double quote character in the text. 187 Will expand a leading ~ or ~user to a valid home directory. 188 Will expand a leading $VAR to an environment variable name.""" 189 import glob 190 import os 191 192 # save the leading quote character so we can re-add it later 193 quote = text[0] 194 # strip the leading quote character 195 path = text[1:] 196 197 # expand a tilde (~) or a leading environment variable in the text 198 path = os.path.expanduser( path ) 199 path = os.path.expandvars( path ) 200 201 # append the any match character to send to the glob routine 202 path = path + "*" 203 204 # use the glob module to get all of the matches 205 rawMatches = glob.glob( path ) 206 207 # re-prefix the text with the quoting character and append the correct 208 # terminating character depending on the type of match that was found. 209 # Directories are terminated with '/' and files with an ending quote. 210 matches = [] 211 for entry in rawMatches: 212 if os.path.isdir( entry ): 213 matches.append( quote + entry + os.sep ) 214 elif os.path.isfile( entry ): 215 matches.append( quote + entry + quote ) 216 else: 217 matches.append( quote + entry ) 218 return matches 219 158 220 def get_class_members(klass): 159 221 ret = dir(klass) 160 222 if hasattr(klass,'__bases__'):