Mercurial > dotfiles
comparison unixSoft/lib/python/rlcompleter_ng.py @ 0:c30d68fbd368
Initial import from svn.
| author | Augie Fackler <durin42@gmail.com> |
|---|---|
| date | Wed, 26 Nov 2008 10:56:09 -0600 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:c30d68fbd368 |
|---|---|
| 1 """ | |
| 2 rlcompleter_ng | |
| 3 ============== | |
| 4 | |
| 5 This module represents an alternative to rlcompleter and rlcompleter2, | |
| 6 for those who don't like their default behaviour. | |
| 7 | |
| 8 There are two main differences between stdlib's rlcompleter and | |
| 9 rlcompleter_ng: | |
| 10 | |
| 11 - when doing something like a.b.c.<TAB>, rlcompleter prepends a.b.c | |
| 12 to all the completions it finds; rlcompleter_ng displays only the | |
| 13 attributes, making the screen less cluttered; | |
| 14 | |
| 15 - you can use the <TAB> key both to indent (when the current line is | |
| 16 blank) or to complete (when it's not blank); | |
| 17 | |
| 18 - more important, rlcompleter_ng prints the various attributes found | |
| 19 in different colors depending on their type. | |
| 20 | |
| 21 Unfortunately, the default version of libreadline don't support | |
| 22 colored completions, so you need to patch it to fully exploid | |
| 23 rlcompleter_ng capabilities. | |
| 24 | |
| 25 You can find the patch here: | |
| 26 http://codespeak.net/svn/user/antocuni/hack/readline-escape.patch | |
| 27 | |
| 28 Alternatively, you can download the Ubuntu Hardy i386 package from here (thanks | |
| 29 to Alexander Schremmer): | |
| 30 http://antosreadlineforhardy.alexanderweb.de/libreadline5_5.2-3build1pypy_i386.deb | |
| 31 | |
| 32 Installation | |
| 33 ------------ | |
| 34 | |
| 35 Simply put the file rlcompleter_ng.py in a directory which is in your | |
| 36 PYTHONPATH. | |
| 37 | |
| 38 Configuration | |
| 39 ------------- | |
| 40 | |
| 41 Since it requires a patched version of libreadline, coloured | |
| 42 completions are disabled by default. | |
| 43 | |
| 44 To customize the configuration of rlcompleter_ng, you need to put a | |
| 45 file named .rlcompleter_ngrc.py in your home directory. The file must | |
| 46 contain a class named ``Config`` inheriting from ``DefaultConfig`` and | |
| 47 overridding the desired values. | |
| 48 | |
| 49 You can find a sample configuration file, which enables colors, here: | |
| 50 http://codespeak.net/svn/user/antocuni/hack/rlcompleter_ngrc.py | |
| 51 | |
| 52 Usage | |
| 53 ----- | |
| 54 | |
| 55 From the interactive prompt, import rlcompleter_ng and call setup(): | |
| 56 | |
| 57 >>> import rlcompleter_ng | |
| 58 >>> rlcompleter_ng.setup() | |
| 59 | |
| 60 Alternatively, you can put these lines in some file that it's | |
| 61 referenced by the PYTHONSTARTUP environment variable, so that | |
| 62 completions is always enabled. | |
| 63 """ | |
| 64 | |
| 65 __version__='0.1' | |
| 66 __author__ ='Antonio Cuni <anto.cuni@gmail.com>' | |
| 67 __url__='http://codespeak.net/svn/user/antocuni/hack/rlcompleter_ng.py' | |
| 68 | |
| 69 | |
| 70 import readline | |
| 71 import rlcompleter | |
| 72 import types | |
| 73 import os.path | |
| 74 from itertools import izip, count | |
| 75 | |
| 76 class colors: | |
| 77 black = '30' | |
| 78 darkred = '31' | |
| 79 darkgreen = '32' | |
| 80 brown = '33' | |
| 81 darkblue = '34' | |
| 82 purple = '35' | |
| 83 teal = '36' | |
| 84 lightgray = '37' | |
| 85 darkgray = '30;01' | |
| 86 red = '31;01' | |
| 87 green = '32;01' | |
| 88 yellow = '33;01' | |
| 89 blue = '34;01' | |
| 90 fuchsia = '35;01' | |
| 91 turquoise = '36;01' | |
| 92 white = '37;01' | |
| 93 | |
| 94 | |
| 95 class DefaultConfig: | |
| 96 | |
| 97 # WARNING: for this option to work properly, you need to patch readline with this: | |
| 98 # http://codespeak.net/svn/user/antocuni/hack/readline-escape.patch | |
| 99 use_colors = False | |
| 100 | |
| 101 color_by_type = { | |
| 102 types.BuiltinMethodType: colors.turquoise, | |
| 103 types.BuiltinMethodType: colors.turquoise, | |
| 104 types.MethodType: colors.turquoise, | |
| 105 type((42).__add__): colors.turquoise, | |
| 106 type(int.__add__): colors.turquoise, | |
| 107 type(str.replace): colors.turquoise, | |
| 108 | |
| 109 types.FunctionType: colors.blue, | |
| 110 types.BuiltinFunctionType: colors.blue, | |
| 111 | |
| 112 types.ClassType: colors.fuchsia, | |
| 113 type: colors.fuchsia, | |
| 114 | |
| 115 types.ModuleType: colors.teal, | |
| 116 types.NoneType: colors.lightgray, | |
| 117 str: colors.green, | |
| 118 unicode: colors.green, | |
| 119 int: colors.yellow, | |
| 120 float: colors.yellow, | |
| 121 complex: colors.yellow, | |
| 122 bool: colors.yellow, | |
| 123 } | |
| 124 | |
| 125 | |
| 126 def setcolor(s, color): | |
| 127 return '\x1b[%sm%s\x1b[00m' % (color, s) | |
| 128 | |
| 129 | |
| 130 class ConfigurableClass: | |
| 131 DefaultConfig = None | |
| 132 config_filename = None | |
| 133 | |
| 134 def get_config(self, Config): | |
| 135 if Config is not None: | |
| 136 return Config() | |
| 137 # try to load config from the ~/filename file | |
| 138 filename = '~/' + self.config_filename | |
| 139 rcfile = os.path.expanduser(filename) | |
| 140 if os.path.exists(rcfile): | |
| 141 mydict = {} | |
| 142 try: | |
| 143 execfile(rcfile, mydict) | |
| 144 return mydict['Config']() | |
| 145 except Exception, e: | |
| 146 print '** error when importing %s: %s **' % (s, e) | |
| 147 return self.DefaultConfig() | |
| 148 | |
| 149 | |
| 150 class Completer(rlcompleter.Completer, ConfigurableClass): | |
| 151 """ | |
| 152 When doing someting like a.b.<TAB>, display only the attributes of | |
| 153 b instead of the full a.b.attr string. | |
| 154 | |
| 155 Optionally, display the various completions in different colors | |
| 156 depending on the type. | |
| 157 """ | |
| 158 | |
| 159 DefaultConfig = DefaultConfig | |
| 160 config_filename = '.rlcompleter_ngrc.py' | |
| 161 | |
| 162 def __init__(self, namespace = None, Config=None): | |
| 163 rlcompleter.Completer.__init__(self, namespace) | |
| 164 self.config = self.get_config(Config) | |
| 165 if self.config.use_colors: | |
| 166 readline.parse_and_bind('set dont-escape-ctrl-chars on') | |
| 167 | |
| 168 def complete(self, text, state): | |
| 169 """ | |
| 170 stolen from: | |
| 171 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812 | |
| 172 """ | |
| 173 if text == "": | |
| 174 return ['\t',None][state] | |
| 175 else: | |
| 176 return rlcompleter.Completer.complete(self,text,state) | |
| 177 | |
| 178 def global_matches(self, text): | |
| 179 import keyword | |
| 180 names = rlcompleter.Completer.global_matches(self, text) | |
| 181 prefix = commonprefix(names) | |
| 182 if prefix and prefix != text: | |
| 183 return [prefix] | |
| 184 | |
| 185 names.sort() | |
| 186 values = [] | |
| 187 for name in names: | |
| 188 if name in keyword.kwlist: | |
| 189 values.append(None) | |
| 190 else: | |
| 191 values.append(eval(name, self.namespace)) | |
| 192 matches = [self.color_for_obj(i, name, obj) | |
| 193 for i, name, obj | |
| 194 in izip(count(), names, values)] | |
| 195 return matches + [' '] | |
| 196 | |
| 197 def attr_matches(self, text): | |
| 198 import re | |
| 199 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) | |
| 200 if not m: | |
| 201 return | |
| 202 expr, attr = m.group(1, 3) | |
| 203 object = eval(expr, self.namespace) | |
| 204 names = [] | |
| 205 values = [] | |
| 206 n = len(attr) | |
| 207 for word in dir(object): | |
| 208 if word[:n] == attr and word != "__builtins__": | |
| 209 names.append(word) | |
| 210 values.append(getattr(object, word)) | |
| 211 | |
| 212 prefix = commonprefix(names) | |
| 213 if prefix and prefix != attr: | |
| 214 return ['%s.%s' % (expr, prefix)] # autocomplete prefix | |
| 215 | |
| 216 matches = [self.color_for_obj(i, name, value) | |
| 217 for i, name, value | |
| 218 in izip(count(), names, values)] | |
| 219 return matches + [' '] | |
| 220 | |
| 221 def color_for_obj(self, i, name, value): | |
| 222 if not self.config.use_colors: | |
| 223 return name | |
| 224 t = type(value) | |
| 225 color = self.config.color_by_type.get(t, '00') | |
| 226 # hack hack hack | |
| 227 # prepend a fake escape sequence, so that readline can sort the matches correctly | |
| 228 return '\x1b[%03d;00m' % i + setcolor(name, color) | |
| 229 | |
| 230 | |
| 231 # stolen from rlcompleter2 | |
| 232 def commonprefix(names, base = ''): | |
| 233 """ return the common prefix of all 'names' starting with 'base' | |
| 234 """ | |
| 235 def commonfunc(s1,s2): | |
| 236 while not s2.startswith(s1): | |
| 237 s1=s1[:-1] | |
| 238 return s1 | |
| 239 | |
| 240 if base: | |
| 241 names = filter(lambda x, base=base: x.startswith(base), names) | |
| 242 if not names: | |
| 243 return '' | |
| 244 return reduce(commonfunc,names) | |
| 245 | |
| 246 | |
| 247 def setup(): | |
| 248 completer = Completer() | |
| 249 readline.parse_and_bind('tab: complete') | |
| 250 readline.set_completer(completer.complete) |
