##// END OF EJS Templates
Removed a lot of code from here, which will be committed next....
Fernando Perez -
Show More
@@ -1,4 +1,3 b''
1
2 1 """ Implementations for various useful completers
3 2
4 3 See extensions/ipy_stock_completers.py on examples of how to enable a completer,
@@ -6,150 +5,21 b' but the basic idea is to do:'
6 5
7 6 ip.set_hook('complete_command', svn_completer, str_key = 'svn')
8 7
8 NOTE: some of the completers that used to be here, the ones used always by
9 default (loaded before by ipy_stock_completers) have been moved into
10 core.completerlib, where they will be further cleaned up and maintained. The
11 rest of this file would need to be well commented, cleaned up and tested for
12 inclusion into the core.
9 13 """
10 from IPython.core import ipapi
11 from IPython.core.error import TryNext
12 14
13 15 import glob,os,shlex,sys
14 16 import inspect
15 17 from time import time
16 18 from zipimport import zipimporter
17 ip = ipapi.get()
18
19 try:
20 set
21 except:
22 from sets import Set as set
23
24 TIMEOUT_STORAGE = 3 #Time in seconds after which the rootmodules will be stored
25 TIMEOUT_GIVEUP = 20 #Time in seconds after which we give up
26
27 def quick_completer(cmd, completions):
28 """ Easily create a trivial completer for a command.
29
30 Takes either a list of completions, or all completions in string
31 (that will be split on whitespace)
32
33 Example::
34
35 [d:\ipython]|1> import ipy_completers
36 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
37 [d:\ipython]|3> foo b<TAB>
38 bar baz
39 [d:\ipython]|3> foo ba
40 """
41 if isinstance(completions, basestring):
42
43 completions = completions.split()
44 def do_complete(self,event):
45 return completions
46
47 ip.set_hook('complete_command',do_complete, str_key = cmd)
48
49 def getRootModules():
50 """
51 Returns a list containing the names of all the modules available in the
52 folders of the pythonpath.
53 """
54 modules = []
55 if ip.db.has_key('rootmodules'):
56 return ip.db['rootmodules']
57 t = time()
58 store = False
59 for path in sys.path:
60 modules += moduleList(path)
61 if time() - t >= TIMEOUT_STORAGE and not store:
62 store = True
63 print "\nCaching the list of root modules, please wait!"
64 print "(This will only be done once - type '%rehashx' to " + \
65 "reset cache!)"
66 print
67 if time() - t > TIMEOUT_GIVEUP:
68 print "This is taking too long, we give up."
69 print
70 ip.db['rootmodules'] = []
71 return []
72
73 modules += sys.builtin_module_names
74
75 modules = list(set(modules))
76 if '__init__' in modules:
77 modules.remove('__init__')
78 modules = list(set(modules))
79 if store:
80 ip.db['rootmodules'] = modules
81 return modules
82
83 def moduleList(path):
84 """
85 Return the list containing the names of the modules available in the given
86 folder.
87 """
88 19
89 if os.path.isdir(path):
90 folder_list = os.listdir(path)
91 elif path.endswith('.egg'):
92 try:
93 folder_list = [f for f in zipimporter(path)._files]
94 except:
95 folder_list = []
96 else:
97 folder_list = []
98 #folder_list = glob.glob(os.path.join(path,'*'))
99 folder_list = [p for p in folder_list \
100 if os.path.exists(os.path.join(path, p,'__init__.py'))\
101 or p[-3:] in ('.py','.so')\
102 or p[-4:] in ('.pyc','.pyo','.pyd')]
103
104 folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
105 return folder_list
106
107 def moduleCompletion(line):
108 """
109 Returns a list containing the completion possibilities for an import line.
110 The line looks like this :
111 'import xml.d'
112 'from xml.dom import'
113 """
114 def tryImport(mod, only_modules=False):
115 def isImportable(module, attr):
116 if only_modules:
117 return inspect.ismodule(getattr(module, attr))
118 else:
119 return not(attr[:2] == '__' and attr[-2:] == '__')
120 try:
121 m = __import__(mod)
122 except:
123 return []
124 mods = mod.split('.')
125 for module in mods[1:]:
126 m = getattr(m,module)
127 if (not hasattr(m, '__file__')) or (not only_modules) or\
128 (hasattr(m, '__file__') and '__init__' in m.__file__):
129 completion_list = [attr for attr in dir(m) if isImportable(m, attr)]
130 completion_list.extend(getattr(m,'__all__',[]))
131 if hasattr(m, '__file__') and '__init__' in m.__file__:
132 completion_list.extend(moduleList(os.path.dirname(m.__file__)))
133 completion_list = list(set(completion_list))
134 if '__init__' in completion_list:
135 completion_list.remove('__init__')
136 return completion_list
137
138 words = line.split(' ')
139 if len(words) == 3 and words[0] == 'from':
140 return ['import ']
141 if len(words) < 3 and (words[0] in ['import','from']) :
142 if len(words) == 1:
143 return getRootModules()
144 mod = words[1].split('.')
145 if len(mod) < 2:
146 return getRootModules()
147 completion_list = tryImport('.'.join(mod[:-1]), True)
148 completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
149 return completion_list
150 if len(words) >= 3 and words[0] == 'from':
151 mod = words[1]
152 return tryImport(mod)
20 from IPython.core import ipapi
21 from IPython.core.error import TryNext
22 ip = ipapi.get()
153 23
154 24 def vcs_completer(commands, event):
155 25 """ utility to make writing typical version control app completers easier
@@ -174,20 +44,6 b' def vcs_completer(commands, event):'
174 44 return ip.Completer.file_matches(event.symbol)
175 45
176 46
177 pkg_cache = None
178
179 def module_completer(self,event):
180 """ Give completions after user has typed 'import ...' or 'from ...'"""
181
182 # This works in all versions of python. While 2.5 has
183 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
184 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
185 # of possibly problematic side effects.
186 # This search the folders in the sys.path for available modules.
187
188 return moduleCompletion(event.line)
189
190
191 47 svn_commands = """\
192 48 add blame praise annotate ann cat checkout co cleanup commit ci copy
193 49 cp delete del remove rm diff di export help ? h import info list ls
@@ -252,125 +108,6 b' def bzr_completer(self,event):'
252 108 return bzr_commands()
253 109
254 110
255 def shlex_split(x):
256 """Helper function to split lines into segments."""
257 #shlex.split raise exception if syntax error in sh syntax
258 #for example if no closing " is found. This function keeps dropping
259 #the last character of the line until shlex.split does not raise
260 #exception. Adds end of the line to the result of shlex.split
261 #example: %run "c:/python -> ['%run','"c:/python']
262 endofline=[]
263 while x!="":
264 try:
265 comps=shlex.split(x)
266 if len(endofline)>=1:
267 comps.append("".join(endofline))
268 return comps
269 except ValueError:
270 endofline=[x[-1:]]+endofline
271 x=x[:-1]
272 return ["".join(endofline)]
273
274 def runlistpy(self, event):
275 comps = shlex_split(event.line)
276 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
277
278 #print "\nev=",event # dbg
279 #print "rp=",relpath # dbg
280 #print 'comps=',comps # dbg
281
282 lglob = glob.glob
283 isdir = os.path.isdir
284 if relpath.startswith('~'):
285 relpath = os.path.expanduser(relpath)
286 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*')
287 if isdir(f)]
288
289 # Find if the user has already typed the first filename, after which we
290 # should complete on all files, since after the first one other files may
291 # be arguments to the input script.
292 #filter(
293 if filter(lambda f: f.endswith('.py') or f.endswith('.ipy') or
294 f.endswith('.pyw'),comps):
295 pys = [f.replace('\\','/') for f in lglob('*')]
296 else:
297 pys = [f.replace('\\','/')
298 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
299 lglob(relpath + '*.pyw')]
300 return dirs + pys
301
302
303 greedy_cd_completer = False
304
305 def cd_completer(self, event):
306 relpath = event.symbol
307 #print event # dbg
308 if '-b' in event.line:
309 # return only bookmark completions
310 bkms = self.db.get('bookmarks',{})
311 return bkms.keys()
312
313
314 if event.symbol == '-':
315 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
316 # jump in directory history by number
317 fmt = '-%0' + width_dh +'d [%s]'
318 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
319 if len(ents) > 1:
320 return ents
321 return []
322
323 if event.symbol.startswith('--'):
324 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
325
326 if relpath.startswith('~'):
327 relpath = os.path.expanduser(relpath).replace('\\','/')
328 found = []
329 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
330 if os.path.isdir(f)]:
331 if ' ' in d:
332 # we don't want to deal with any of that, complex code
333 # for this is elsewhere
334 raise TryNext
335 found.append( d )
336
337 if not found:
338 if os.path.isdir(relpath):
339 return [relpath]
340 # if no completions so far, try bookmarks
341 bks = self.db.get('bookmarks',{}).keys()
342 bkmatches = [s for s in bks if s.startswith(event.symbol)]
343 if bkmatches:
344 return bkmatches
345
346 raise TryNext
347
348
349 def single_dir_expand(matches):
350 "Recursively expand match lists containing a single dir."
351
352 if len(matches) == 1 and os.path.isdir(matches[0]):
353 # Takes care of links to directories also. Use '/'
354 # explicitly, even under Windows, so that name completions
355 # don't end up escaped.
356 d = matches[0]
357 if d[-1] in ['/','\\']:
358 d = d[:-1]
359
360 subdirs = [p for p in os.listdir(d) if os.path.isdir( d + '/' + p) and not p.startswith('.')]
361 if subdirs:
362 matches = [ (d + '/' + p) for p in subdirs ]
363 return single_dir_expand(matches)
364 else:
365 return matches
366 else:
367 return matches
368
369 if greedy_cd_completer:
370 return single_dir_expand(found)
371 else:
372 return found
373
374 111 def apt_get_packages(prefix):
375 112 out = os.popen('apt-cache pkgnames')
376 113 for p in out:
@@ -399,4 +136,3 b' def apt_completer(self, event):'
399 136 return apt_commands.split()
400 137
401 138 return list(apt_get_packages(event.symbol))
402
General Comments 0
You need to be logged in to leave comments. Login now