##// END OF EJS Templates
ipy_completers.quick_completer for easy creation of custom completers
vivainio -
Show More
@@ -1,46 +1,47 b''
1 1 # -*- coding: utf-8 -*-
2 2 """ IPython extension: add %clear magic """
3 3
4 4 import IPython.ipapi
5 5 import gc
6 6 ip = IPython.ipapi.get()
7 7
8 8
9 9 def clear_f(self,arg):
10 10 """ Clear various data (e.g. stored history data)
11 11
12 12 %clear out - clear output history
13 13 %clear in - clear input history
14 14 """
15 15
16 16 api = self.getapi()
17 17 for target in arg.split():
18 18 if target == 'out':
19 19 print "Flushing output cache (%d entries)" % len(api.user_ns['_oh'])
20 20 self.outputcache.flush()
21 21 elif target == 'in':
22 22 print "Flushing input history"
23 23 from IPython import iplib
24 24 del self.input_hist[:]
25 25 del self.input_hist_raw[:]
26 26 for n in range(1,self.outputcache.prompt_count + 1):
27 27 key = '_i'+`n`
28 28 try:
29 29 del self.user_ns[key]
30 30 except: pass
31 31 elif target == 'array':
32 32 try:
33 33 pylab=ip.IP.pylab
34 34 for x in self.user_ns.keys():
35 35 if isinstance(self.user_ns[x],pylab.arraytype):
36 36 del self.user_ns[x]
37 37 except AttributeError:
38 38 print "Clear array only available in -pylab mode"
39 39 gc.collect()
40
40 elif target == 'shadow':
41 api.db.hcompress('shadowhist')
41 42
42 43 ip.expose_magic("clear",clear_f)
43 44
44 45
45 46
46 47
@@ -1,323 +1,346 b''
1 1 #!/usr/bin/env python
2 2
3 3 """ Implementations for various useful completers
4 4
5 5 See Extensions/ipy_stock_completers.py on examples of how to enable a completer,
6 6 but the basic idea is to do:
7 7
8 8 ip.set_hook('complete_command', svn_completer, str_key = 'svn')
9 9
10 10 """
11 11 import IPython.ipapi
12 12 import glob,os,shlex,sys
13 13 import inspect
14 14 from time import time
15 15 ip = IPython.ipapi.get()
16 16
17 17 TIMEOUT_STORAGE = 3 #Time in seconds after which the rootmodules will be stored
18 18 TIMEOUT_GIVEUP = 20 #Time in seconds after which we give up
19 19
20 def quick_completer(cmd, completions):
21 """ Easily create a completer a trivial completer for a command.
22
23 Takes either a list of completions, or all completions in string
24 (that will be split on whitespace)
25
26 Example::
27
28 [d:\ipython]|1> import ipy_completers
29 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
30 [d:\ipython]|3> foo boooo
31
32 bar baz
33 [d:\ipython]|3> foo ba
34 """
35 if isinstance(completions, basestring):
36
37 completions = completions.split()
38 def do_complete(self,event):
39 return completions
40
41 ip.set_hook('complete_command',do_complete, str_key = cmd)
42
20 43 def getRootModules():
21 44 """
22 45 Returns a list containing the names of all the modules available in the
23 46 folders of the pythonpath.
24 47 """
25 48 modules = []
26 49 if ip.db.has_key('rootmodules'):
27 50 return ip.db['rootmodules']
28 51 t = time()
29 52 store = False
30 53 for path in sys.path:
31 54 modules += moduleList(path)
32 55 if time() - t >= TIMEOUT_STORAGE and not store:
33 56 store = True
34 57 print "\nCaching the list of root modules, please wait!"
35 58 print "(This will only be done once - type '%rehashx' to " + \
36 59 "reset cache!)"
37 60 print
38 61 if time() - t > TIMEOUT_GIVEUP:
39 62 print "This is taking too long, we give up."
40 63 print
41 64 ip.db['rootmodules'] = []
42 65 return []
43 66
44 67 modules += sys.builtin_module_names
45 68 modules = list(set(modules))
46 69 if '__init__' in modules:
47 70 modules.remove('__init__')
48 71 modules = list(set(modules))
49 72 if store:
50 73 ip.db['rootmodules'] = modules
51 74 return modules
52 75
53 76 def moduleList(path):
54 77 """
55 78 Return the list containing the names of the modules available in the given
56 79 folder.
57 80 """
58 81 if os.path.isdir(path):
59 82 folder_list = os.listdir(path)
60 83 else:
61 84 folder_list = []
62 85 #folder_list = glob.glob(os.path.join(path,'*'))
63 86 folder_list = [path for path in folder_list \
64 87 if os.path.exists(os.path.join(path,'__init__.py'))\
65 88 or path[-3:] in ('.py','.so')\
66 89 or path[-4:] in ('.pyc','.pyo')]
67 90 folder_list += folder_list
68 91 folder_list = [os.path.basename(path).split('.')[0] for path in folder_list]
69 92 return folder_list
70 93
71 94 def moduleCompletion(line):
72 95 """
73 96 Returns a list containing the completion possibilities for an import line.
74 97 The line looks like this :
75 98 'import xml.d'
76 99 'from xml.dom import'
77 100 """
78 101 def tryImport(mod, only_modules=False):
79 102 def isImportable(module, attr):
80 103 if only_modules:
81 104 return inspect.ismodule(getattr(module, attr))
82 105 else:
83 106 return not(attr[:2] == '__' and attr[-2:] == '__')
84 107 try:
85 108 m = __import__(mod)
86 109 except:
87 110 return []
88 111 mods = mod.split('.')
89 112 for module in mods[1:]:
90 113 m = getattr(m,module)
91 114 if (not hasattr(m, '__file__')) or (not only_modules) or\
92 115 (hasattr(m, '__file__') and '__init__' in m.__file__):
93 116 completion_list = [attr for attr in dir(m) if isImportable(m, attr)]
94 117 completion_list.extend(getattr(m,'__all__',[]))
95 118 if hasattr(m, '__file__') and '__init__' in m.__file__:
96 119 completion_list.extend(moduleList(os.path.dirname(m.__file__)))
97 120 completion_list = list(set(completion_list))
98 121 if '__init__' in completion_list:
99 122 completion_list.remove('__init__')
100 123 return completion_list
101 124
102 125 words = line.split(' ')
103 126 if len(words) == 3 and words[0] == 'from':
104 127 return ['import ']
105 128 if len(words) < 3 and (words[0] in ['import','from']) :
106 129 if len(words) == 1:
107 130 return getRootModules()
108 131 mod = words[1].split('.')
109 132 if len(mod) < 2:
110 133 return getRootModules()
111 134 completion_list = tryImport('.'.join(mod[:-1]), True)
112 135 completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
113 136 return completion_list
114 137 if len(words) >= 3 and words[0] == 'from':
115 138 mod = words[1]
116 139 return tryImport(mod)
117 140
118 141 def vcs_completer(commands, event):
119 142 """ utility to make writing typical version control app completers easier
120 143
121 144 VCS command line apps typically have the format:
122 145
123 146 [sudo ]PROGNAME [help] [command] file file...
124 147
125 148 """
126 149
127 150
128 151 cmd_param = event.line.split()
129 152 if event.line.endswith(' '):
130 153 cmd_param.append('')
131 154
132 155 if cmd_param[0] == 'sudo':
133 156 cmd_param = cmd_param[1:]
134 157
135 158 if len(cmd_param) == 2 or 'help' in cmd_param:
136 159 return commands.split()
137 160
138 161 return ip.IP.Completer.file_matches(event.symbol)
139 162
140 163
141 164
142 165 def apt_completers(self, event):
143 166 """ This should return a list of strings with possible completions.
144 167
145 168 Note that all the included strings that don't start with event.symbol
146 169 are removed, in order to not confuse readline.
147 170
148 171 """
149 172 # print event # dbg
150 173
151 174 # commands are only suggested for the 'command' part of package manager
152 175 # invocation
153 176
154 177 cmd = (event.line + "<placeholder>").rsplit(None,1)[0]
155 178 # print cmd
156 179 if cmd.endswith('apt-get') or cmd.endswith('yum'):
157 180 return ['update', 'upgrade', 'install', 'remove']
158 181
159 182 # later on, add dpkg -l / whatever to get list of possible
160 183 # packages, add switches etc. for the rest of command line
161 184 # filling
162 185
163 186 raise IPython.ipapi.TryNext
164 187
165 188
166 189
167 190 pkg_cache = None
168 191
169 192 def module_completer(self,event):
170 193 """ Give completions after user has typed 'import ...' or 'from ...'"""
171 194
172 195 # This works in all versions of python. While 2.5 has
173 196 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
174 197 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
175 198 # of possibly problematic side effects.
176 199 # This search the folders in the sys.path for available modules.
177 200
178 201 return moduleCompletion(event.line)
179 202
180 203
181 204 svn_commands = """\
182 205 add blame praise annotate ann cat checkout co cleanup commit ci copy
183 206 cp delete del remove rm diff di export help ? h import info list ls
184 207 lock log merge mkdir move mv rename ren propdel pdel pd propedit pedit
185 208 pe propget pget pg proplist plist pl propset pset ps resolved revert
186 209 status stat st switch sw unlock update
187 210 """
188 211
189 212 def svn_completer(self,event):
190 213 return vcs_completer(svn_commands, event)
191 214
192 215
193 216 hg_commands = """
194 217 add addremove annotate archive backout branch branches bundle cat
195 218 clone commit copy diff export grep heads help identify import incoming
196 219 init locate log manifest merge outgoing parents paths pull push
197 220 qapplied qclone qcommit qdelete qdiff qfold qguard qheader qimport
198 221 qinit qnew qnext qpop qprev qpush qrefresh qrename qrestore qsave
199 222 qselect qseries qtop qunapplied recover remove rename revert rollback
200 223 root serve showconfig status strip tag tags tip unbundle update verify
201 224 version
202 225 """
203 226
204 227 def hg_completer(self,event):
205 228 """ Completer for mercurial commands """
206 229
207 230 return vcs_completer(hg_commands, event)
208 231
209 232
210 233
211 234 bzr_commands = """
212 235 add annotate bind branch break-lock bundle-revisions cat check
213 236 checkout commit conflicts deleted diff export gannotate gbranch
214 237 gcommit gdiff help ignore ignored info init init-repository inventory
215 238 log merge missing mkdir mv nick pull push reconcile register-branch
216 239 remerge remove renames resolve revert revno root serve sign-my-commits
217 240 status testament unbind uncommit unknowns update upgrade version
218 241 version-info visualise whoami
219 242 """
220 243
221 244 def bzr_completer(self,event):
222 245 """ Completer for bazaar commands """
223 246 cmd_param = event.line.split()
224 247 if event.line.endswith(' '):
225 248 cmd_param.append('')
226 249
227 250 if len(cmd_param) > 2:
228 251 cmd = cmd_param[1]
229 252 param = cmd_param[-1]
230 253 output_file = (param == '--output=')
231 254 if cmd == 'help':
232 255 return bzr_commands.split()
233 256 elif cmd in ['bundle-revisions','conflicts',
234 257 'deleted','nick','register-branch',
235 258 'serve','unbind','upgrade','version',
236 259 'whoami'] and not output_file:
237 260 return []
238 261 else:
239 262 # the rest are probably file names
240 263 return ip.IP.Completer.file_matches(event.symbol)
241 264
242 265 return bzr_commands.split()
243 266
244 267
245 268 def shlex_split(x):
246 269 """Helper function to split lines into segments."""
247 270 #shlex.split raise exception if syntax error in sh syntax
248 271 #for example if no closing " is found. This function keeps dropping
249 272 #the last character of the line until shlex.split does not raise
250 273 #exception. Adds end of the line to the result of shlex.split
251 274 #example: %run "c:/python -> ['%run','"c:/python']
252 275 endofline=[]
253 276 while x!="":
254 277 try:
255 278 comps=shlex.split(x)
256 279 if len(endofline)>=1:
257 280 comps.append("".join(endofline))
258 281 return comps
259 282 except ValueError:
260 283 endofline=[x[-1:]]+endofline
261 284 x=x[:-1]
262 285 return ["".join(endofline)]
263 286
264 287 def runlistpy(self, event):
265 288 comps = shlex_split(event.line)
266 289 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
267 290
268 291 #print "\nev=",event # dbg
269 292 #print "rp=",relpath # dbg
270 293 #print 'comps=',comps # dbg
271 294
272 295 lglob = glob.glob
273 296 isdir = os.path.isdir
274 297 if relpath.startswith('~'):
275 298 relpath = os.path.expanduser(relpath)
276 299 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*')
277 300 if isdir(f)]
278 301
279 302 # Find if the user has already typed the first filename, after which we
280 303 # should complete on all files, since after the first one other files may
281 304 # be arguments to the input script.
282 305 #filter(
283 306 if filter(lambda f: f.endswith('.py') or f.endswith('.ipy'),comps):
284 307 pys = [f.replace('\\','/') for f in lglob('*')]
285 308 else:
286 309 pys = [f.replace('\\','/')
287 310 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy')]
288 311 return dirs + pys
289 312
290 313
291 314 def cd_completer(self, event):
292 315 relpath = event.symbol
293 316 #print event # dbg
294 317 if '-b' in event.line:
295 318 # return only bookmark completions
296 319 bkms = self.db.get('bookmarks',{})
297 320 return bkms.keys()
298 321
299 322
300 323 if event.symbol == '-':
301 324 # jump in directory history by number
302 325 ents = ['-%d [%s]' % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
303 326 if len(ents) > 1:
304 327 return ents
305 328 return []
306 329
307 330 if relpath.startswith('~'):
308 331 relpath = os.path.expanduser(relpath).replace('\\','/')
309 332 found = []
310 333 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
311 334 if os.path.isdir(f)]:
312 335 if ' ' in d:
313 336 # we don't want to deal with any of that, complex code
314 337 # for this is elsewhere
315 338 raise IPython.ipapi.TryNext
316 339 found.append( d )
317 340
318 341 if not found:
319 342 if os.path.isdir(relpath):
320 343 return [relpath]
321 344 raise IPython.ipapi.TryNext
322 345 return found
323 346
General Comments 0
You need to be logged in to leave comments. Login now