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)