##// END OF EJS Templates
Restored major default completer functionality (cd, import, run)....
Fernando Perez -
Show More
@@ -0,0 +1,337 b''
1 """Implementations for various useful completers.
2
3 These are all loaded by default by IPython.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2010 The IPython Development Team.
7 #
8 # Distributed under the terms of the BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
17
18 # Stdlib imports
19 import glob
20 import inspect
21 import os
22 import re
23 import shlex
24 import sys
25
26 # Third-party imports
27 from time import time
28 from zipimport import zipimporter
29
30 # Our own imports
31 from IPython.core.error import TryNext
32
33 # FIXME: this should be pulled in with the right call via the component system
34 from IPython.core.ipapi import get as get_ipython
35
36 #-----------------------------------------------------------------------------
37 # Globals and constants
38 #-----------------------------------------------------------------------------
39
40 # Time in seconds after which the rootmodules will be stored permanently in the
41 # ipython ip.db database (kept in the user's .ipython dir).
42 TIMEOUT_STORAGE = 2
43
44 # Time in seconds after which we give up
45 TIMEOUT_GIVEUP = 20
46
47 # Regular expression for the python import statement
48 import_re = re.compile(r'.*(\.so|\.py[cod]?)$')
49
50 # RE for the ipython %run command (python + ipython scripts)
51 magic_run_re = re.compile(r'.*(\.ipy|\.py[w]?)$')
52
53 #-----------------------------------------------------------------------------
54 # Local utilities
55 #-----------------------------------------------------------------------------
56
57 def shlex_split(x):
58 """Helper function to split lines into segments.
59 """
60 # shlex.split raises an exception if there is a syntax error in sh syntax
61 # for example if no closing " is found. This function keeps dropping the
62 # last character of the line until shlex.split does not raise
63 # an exception. It adds end of the line to the result of shlex.split
64 #
65 # Example:
66 # %run "c:/python -> ['%run','"c:/python']
67
68 endofline = []
69 while x != '':
70 try:
71 comps = shlex.split(x)
72 if len(endofline) >= 1:
73 comps.append(''.join(endofline))
74 return comps
75
76 except ValueError:
77 endofline = [x[-1:]]+endofline
78 x = x[:-1]
79
80 return [''.join(endofline)]
81
82 def module_list(path):
83 """
84 Return the list containing the names of the modules available in the given
85 folder.
86 """
87
88 if os.path.isdir(path):
89 folder_list = os.listdir(path)
90 elif path.endswith('.egg'):
91 try:
92 folder_list = [f for f in zipimporter(path)._files]
93 except:
94 folder_list = []
95 else:
96 folder_list = []
97
98 if not folder_list:
99 return []
100
101 # A few local constants to be used in loops below
102 isfile = os.path.isfile
103 pjoin = os.path.join
104 basename = os.path.basename
105
106 # Now find actual path matches for packages or modules
107 folder_list = [p for p in folder_list
108 if isfile(pjoin(path, p,'__init__.py'))
109 or import_re.match(p) ]
110
111 return [basename(p).split('.')[0] for p in folder_list]
112
113 def get_root_modules():
114 """
115 Returns a list containing the names of all the modules available in the
116 folders of the pythonpath.
117 """
118 ip = get_ipython()
119
120 if 'rootmodules' in ip.db:
121 return ip.db['rootmodules']
122
123 t = time()
124 store = False
125 modules = list(sys.builtin_module_names)
126 for path in sys.path:
127 modules += module_list(path)
128 if time() - t >= TIMEOUT_STORAGE and not store:
129 store = True
130 print("\nCaching the list of root modules, please wait!")
131 print("(This will only be done once - type '%rehashx' to "
132 "reset cache!)\n")
133 sys.stdout.flush()
134 if time() - t > TIMEOUT_GIVEUP:
135 print("This is taking too long, we give up.\n")
136 ip.db['rootmodules'] = []
137 return []
138
139 modules = set(modules)
140 if '__init__' in modules:
141 modules.remove('__init__')
142 modules = list(modules)
143 if store:
144 ip.db['rootmodules'] = modules
145 return modules
146
147
148 def is_importable(module, attr, only_modules):
149 if only_modules:
150 return inspect.ismodule(getattr(module, attr))
151 else:
152 return not(attr[:2] == '__' and attr[-2:] == '__')
153
154
155 def try_import(mod, only_modules=False):
156 try:
157 m = __import__(mod)
158 except:
159 return []
160 mods = mod.split('.')
161 for module in mods[1:]:
162 m = getattr(m, module)
163
164 m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__
165
166 completions = []
167 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
168 completions.extend( [attr for attr in dir(m) if
169 is_importable(m, attr, only_modules)])
170
171 completions.extend(getattr(m, '__all__', []))
172 if m_is_init:
173 completions.extend(module_list(os.path.dirname(m.__file__)))
174 completions = set(completions)
175 if '__init__' in completions:
176 completions.remove('__init__')
177 return list(completions)
178
179
180 #-----------------------------------------------------------------------------
181 # Completion-related functions.
182 #-----------------------------------------------------------------------------
183
184 def quick_completer(cmd, completions):
185 """ Easily create a trivial completer for a command.
186
187 Takes either a list of completions, or all completions in string (that will
188 be split on whitespace).
189
190 Example::
191
192 [d:\ipython]|1> import ipy_completers
193 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
194 [d:\ipython]|3> foo b<TAB>
195 bar baz
196 [d:\ipython]|3> foo ba
197 """
198
199 if isinstance(completions, basestring):
200 completions = completions.split()
201
202 def do_complete(self, event):
203 return completions
204
205 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
206
207
208 def module_completion(line):
209 """
210 Returns a list containing the completion possibilities for an import line.
211
212 The line looks like this :
213 'import xml.d'
214 'from xml.dom import'
215 """
216
217 words = line.split(' ')
218 nwords = len(words)
219
220 # from whatever <tab> -> 'import '
221 if nwords == 3 and words[0] == 'from':
222 return ['import ']
223
224 # 'from xy<tab>' or 'import xy<tab>'
225 if nwords < 3 and (words[0] in ['import','from']) :
226 if nwords == 1:
227 return get_root_modules()
228 mod = words[1].split('.')
229 if len(mod) < 2:
230 return get_root_modules()
231 completion_list = try_import('.'.join(mod[:-1]), True)
232 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
233
234 # 'from xyz import abc<tab>'
235 if nwords >= 3 and words[0] == 'from':
236 mod = words[1]
237 return try_import(mod)
238
239 #-----------------------------------------------------------------------------
240 # Completers
241 #-----------------------------------------------------------------------------
242 # These all have the func(self, event) signature to be used as custom
243 # completers
244
245 def module_completer(self,event):
246 """Give completions after user has typed 'import ...' or 'from ...'"""
247
248 # This works in all versions of python. While 2.5 has
249 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
250 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
251 # of possibly problematic side effects.
252 # This search the folders in the sys.path for available modules.
253
254 return module_completion(event.line)
255
256
257 def magic_run_completer(self, event):
258 """Complete files that end in .py or .ipy for the %run command.
259 """
260 comps = shlex_split(event.line)
261 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
262
263 #print "\nev=",event # dbg
264 #print "rp=",relpath # dbg
265 #print 'comps=',comps # dbg
266
267 lglob = glob.glob
268 isdir = os.path.isdir
269 if relpath.startswith('~'):
270 relpath = os.path.expanduser(relpath)
271 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
272
273 # Find if the user has already typed the first filename, after which we
274 # should complete on all files, since after the first one other files may
275 # be arguments to the input script.
276
277 if filter(magic_run_re.match, comps):
278 pys = [f.replace('\\','/') for f in lglob('*')]
279 else:
280 pys = [f.replace('\\','/')
281 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
282 lglob(relpath + '*.pyw')]
283 return dirs + pys
284
285
286 def cd_completer(self, event):
287 """Completer function for cd, which only returns directories."""
288 ip = get_ipython()
289 relpath = event.symbol
290
291 #print(event) # dbg
292 if event.line.endswith('-b') or ' -b ' in event.line:
293 # return only bookmark completions
294 bkms = self.db.get('bookmarks', None)
295 if bkms:
296 return bkms.keys()
297 else:
298 return []
299
300 if event.symbol == '-':
301 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
302 # jump in directory history by number
303 fmt = '-%0' + width_dh +'d [%s]'
304 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
305 if len(ents) > 1:
306 return ents
307 return []
308
309 if event.symbol.startswith('--'):
310 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
311
312 if relpath.startswith('~'):
313 relpath = os.path.expanduser(relpath).replace('\\','/')
314
315 found = []
316 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
317 if os.path.isdir(f)]:
318 if ' ' in d:
319 # we don't want to deal with any of that, complex code
320 # for this is elsewhere
321 raise TryNext
322
323 found.append( d )
324
325 if not found:
326 if os.path.isdir(relpath):
327 return [relpath]
328
329 # if no completions so far, try bookmarks
330 bks = self.db.get('bookmarks',{}).keys()
331 bkmatches = [s for s in bks if s.startswith(event.symbol)]
332 if bkmatches:
333 return bkmatches
334
335 raise TryNext
336
337 return found
@@ -80,8 +80,8 b' import sys'
80
80
81 from IPython.core.error import TryNext
81 from IPython.core.error import TryNext
82 from IPython.core.prefilter import ESC_MAGIC
82 from IPython.core.prefilter import ESC_MAGIC
83 from IPython.utils import generics, io
83 from IPython.utils import generics
84 from IPython.utils.frame import debugx
84 from IPython.utils import io
85 from IPython.utils.dir2 import dir2
85 from IPython.utils.dir2 import dir2
86
86
87 #-----------------------------------------------------------------------------
87 #-----------------------------------------------------------------------------
@@ -619,17 +619,21 b' class IPCompleter(Completer):'
619 argMatches.append("%s=" %namedArg)
619 argMatches.append("%s=" %namedArg)
620 return argMatches
620 return argMatches
621
621
622 def dispatch_custom_completer(self,text):
622 def dispatch_custom_completer(self, text):
623 #print "Custom! '%s' %s" % (text, self.custom_completers) # dbg
623 #print "Custom! '%s' %s" % (text, self.custom_completers) # dbg
624 line = self.line_buffer
624 line = self.line_buffer
625 if not line.strip():
625 if not line.strip():
626 return None
626 return None
627
627
628 # Create a little structure to pass all the relevant information about
629 # the current completion to any custom completer.
628 event = Bunch()
630 event = Bunch()
629 event.line = line
631 event.line = line
630 event.symbol = text
632 event.symbol = text
631 cmd = line.split(None,1)[0]
633 cmd = line.split(None,1)[0]
632 event.command = cmd
634 event.command = cmd
635 event.text_until_cursor = self.text_until_cursor
636
633 #print "\ncustom:{%s]\n" % event # dbg
637 #print "\ncustom:{%s]\n" % event # dbg
634
638
635 # for foo etc, try also to find completer for %foo
639 # for foo etc, try also to find completer for %foo
@@ -697,7 +701,6 b' class IPCompleter(Completer):'
697 if line_buffer is None:
701 if line_buffer is None:
698 line_buffer = text
702 line_buffer = text
699
703
700 magic_escape = self.magic_escape
701 self.line_buffer = line_buffer
704 self.line_buffer = line_buffer
702 self.text_until_cursor = self.line_buffer[:cursor_pos]
705 self.text_until_cursor = self.line_buffer[:cursor_pos]
703 #io.rprint('\nCOMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
706 #io.rprint('\nCOMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
@@ -767,16 +770,24 b' class IPCompleter(Completer):'
767 sys.stdout.flush()
770 sys.stdout.flush()
768 return None
771 return None
769
772
770 # This method computes the self.matches array
773 # Note: debugging exceptions that may occur in completion is very
771 self.complete(text, line_buffer, cursor_pos)
774 # tricky, because readline unconditionally silences them. So if
772
775 # during development you suspect a bug in the completion code, turn
773 # Debug version, since readline silences all exceptions making it
776 # this flag on temporarily by uncommenting the second form (don't
774 # impossible to debug any problem in the above code
777 # flip the value in the first line, as the '# dbg' marker can be
775
778 # automatically detected and is used elsewhere).
776 ## try:
779 DEBUG = False
777 ## self.complete(text, line_buffer, cursor_pos)
780 #DEBUG = True # dbg
778 ## except:
781 if DEBUG:
779 ## import traceback; traceback.print_exc()
782 try:
783 self.complete(text, line_buffer, cursor_pos)
784 except:
785 import traceback; traceback.print_exc()
786 else:
787 # The normal production version is here
788
789 # This method computes the self.matches array
790 self.complete(text, line_buffer, cursor_pos)
780
791
781 try:
792 try:
782 return self.matches[state]
793 return self.matches[state]
@@ -1642,16 +1642,29 b' class InteractiveShell(Configurable, Magic):'
1642 (typically over the network by remote frontends).
1642 (typically over the network by remote frontends).
1643 """
1643 """
1644 from IPython.core.completer import IPCompleter
1644 from IPython.core.completer import IPCompleter
1645 from IPython.core.completerlib import (module_completer,
1646 magic_run_completer, cd_completer)
1647
1645 self.Completer = IPCompleter(self,
1648 self.Completer = IPCompleter(self,
1646 self.user_ns,
1649 self.user_ns,
1647 self.user_global_ns,
1650 self.user_global_ns,
1648 self.readline_omit__names,
1651 self.readline_omit__names,
1649 self.alias_manager.alias_table,
1652 self.alias_manager.alias_table,
1650 self.has_readline)
1653 self.has_readline)
1654
1655 # Add custom completers to the basic ones built into IPCompleter
1651 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1656 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1652 self.strdispatchers['complete_command'] = sdisp
1657 self.strdispatchers['complete_command'] = sdisp
1653 self.Completer.custom_completers = sdisp
1658 self.Completer.custom_completers = sdisp
1654
1659
1660 self.set_hook('complete_command', module_completer, str_key = 'import')
1661 self.set_hook('complete_command', module_completer, str_key = 'from')
1662 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
1663 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1664
1665 # Only configure readline if we truly are using readline. IPython can
1666 # do tab-completion over the network, in GUIs, etc, where readline
1667 # itself may be absent
1655 if self.has_readline:
1668 if self.has_readline:
1656 self.set_readline_completer()
1669 self.set_readline_completer()
1657
1670
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now