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) |