##// END OF EJS Templates
Fix bugs with completions of paths that have ~ in them....
Fernando Perez -
Show More
@@ -119,6 +119,52 b' def mark_dirs(matches):'
119 return out
119 return out
120
120
121
121
122 def expand_user(path):
123 """Expand '~'-style usernames in strings.
124
125 This is similar to :func:`os.path.expanduser`, but it computes and returns
126 extra information that will be useful if the input was being used in
127 computing completions, and you wish to return the completions with the
128 original '~' instead of its expanded value.
129
130 Parameters
131 ----------
132 path : str
133 String to be expanded. If no ~ is present, the output is the same as the
134 input.
135
136 Returns
137 -------
138 newpath : str
139 Result of ~ expansion in the input path.
140 tilde_expand : bool
141 Whether any expansion was performed or not.
142 tilde_val : str
143 The value that ~ was replaced with.
144 """
145 # Default values
146 tilde_expand = False
147 tilde_val = ''
148 newpath = path
149
150 if path.startswith('~'):
151 tilde_expand = True
152 rest = path[1:]
153 newpath = os.path.expanduser(path)
154 tilde_val = newpath.replace(rest, '')
155
156 return newpath, tilde_expand, tilde_val
157
158
159 def compress_user(path, tilde_expand, tilde_val):
160 """Does the opposite of expand_user, with its outputs.
161 """
162 if tilde_expand:
163 return path.replace(tilde_val, '~')
164 else:
165 return path
166
167
122 def single_dir_expand(matches):
168 def single_dir_expand(matches):
123 "Recursively expand match lists containing a single dir."
169 "Recursively expand match lists containing a single dir."
124
170
@@ -28,6 +28,7 b' from time import time'
28 from zipimport import zipimporter
28 from zipimport import zipimporter
29
29
30 # Our own imports
30 # Our own imports
31 from IPython.core.completer import expand_user, compress_user
31 from IPython.core.error import TryNext
32 from IPython.core.error import TryNext
32
33
33 # FIXME: this should be pulled in with the right call via the component system
34 # FIXME: this should be pulled in with the right call via the component system
@@ -64,7 +65,11 b' def shlex_split(x):'
64 #
65 #
65 # Example:
66 # Example:
66 # %run "c:/python -> ['%run','"c:/python']
67 # %run "c:/python -> ['%run','"c:/python']
67
68
69 # shlex.split has unicode bugs, so encode first to str
70 if isinstance(x, unicode):
71 x = x.encode(sys.stdin.encoding)
72
68 endofline = []
73 endofline = []
69 while x != '':
74 while x != '':
70 try:
75 try:
@@ -253,6 +258,8 b' def module_completer(self,event):'
253
258
254 return module_completion(event.line)
259 return module_completion(event.line)
255
260
261 # FIXME: there's a lot of logic common to the run, cd and builtin file
262 # completers, that is currently reimplemented in each.
256
263
257 def magic_run_completer(self, event):
264 def magic_run_completer(self, event):
258 """Complete files that end in .py or .ipy for the %run command.
265 """Complete files that end in .py or .ipy for the %run command.
@@ -260,14 +267,14 b' def magic_run_completer(self, event):'
260 comps = shlex_split(event.line)
267 comps = shlex_split(event.line)
261 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
268 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
262
269
263 #print "\nev=",event # dbg
270 #print("\nev=", event) # dbg
264 #print "rp=",relpath # dbg
271 #print("rp=", relpath) # dbg
265 #print 'comps=',comps # dbg
272 #print('comps=', comps) # dbg
266
273
267 lglob = glob.glob
274 lglob = glob.glob
268 isdir = os.path.isdir
275 isdir = os.path.isdir
269 if relpath.startswith('~'):
276 relpath, tilde_expand, tilde_val = expand_user(relpath)
270 relpath = os.path.expanduser(relpath)
277
271 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
278 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
272
279
273 # Find if the user has already typed the first filename, after which we
280 # Find if the user has already typed the first filename, after which we
@@ -280,7 +287,8 b' def magic_run_completer(self, event):'
280 pys = [f.replace('\\','/')
287 pys = [f.replace('\\','/')
281 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
288 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
282 lglob(relpath + '*.pyw')]
289 lglob(relpath + '*.pyw')]
283 return dirs + pys
290 #print('run comp:', dirs+pys) # dbg
291 return [compress_user(p, tilde_expand, tilde_val) for p in dirs+pys]
284
292
285
293
286 def cd_completer(self, event):
294 def cd_completer(self, event):
@@ -308,9 +316,10 b' def cd_completer(self, event):'
308
316
309 if event.symbol.startswith('--'):
317 if event.symbol.startswith('--'):
310 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
318 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
311
319
312 if relpath.startswith('~'):
320 # Expand ~ in path and normalize directory separators.
313 relpath = os.path.expanduser(relpath).replace('\\','/')
321 relpath, tilde_expand, tilde_val = expand_user(relpath)
322 relpath = relpath.replace('\\','/')
314
323
315 found = []
324 found = []
316 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
325 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
@@ -320,11 +329,11 b' def cd_completer(self, event):'
320 # for this is elsewhere
329 # for this is elsewhere
321 raise TryNext
330 raise TryNext
322
331
323 found.append( d )
332 found.append(d)
324
333
325 if not found:
334 if not found:
326 if os.path.isdir(relpath):
335 if os.path.isdir(relpath):
327 return [relpath]
336 return [compress_user(relpath, tilde_expand, tilde_val)]
328
337
329 # if no completions so far, try bookmarks
338 # if no completions so far, try bookmarks
330 bks = self.db.get('bookmarks',{}).keys()
339 bks = self.db.get('bookmarks',{}).keys()
@@ -334,4 +343,4 b' def cd_completer(self, event):'
334
343
335 raise TryNext
344 raise TryNext
336
345
337 return found
346 return [compress_user(p, tilde_expand, tilde_val) for p in found]
General Comments 0
You need to be logged in to leave comments. Login now