##// END OF EJS Templates
Merge pull request #2994 from minrk/expanduser...
Bradley M. Froehle -
r9826:400875c6 merge
parent child Browse files
Show More
@@ -1,726 +1,726 b''
1 1 """Implementation of magic functions for interaction with the OS.
2 2
3 3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 4 builtin.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (c) 2012 The IPython Development Team.
8 8 #
9 9 # Distributed under the terms of the Modified BSD License.
10 10 #
11 11 # The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 # Stdlib
19 19 import io
20 20 import os
21 21 import re
22 22 import sys
23 23 from pprint import pformat
24 24
25 25 # Our own packages
26 26 from IPython.core import magic_arguments
27 27 from IPython.core import oinspect
28 28 from IPython.core import page
29 29 from IPython.core.error import UsageError
30 30 from IPython.core.magic import (
31 31 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
32 32 )
33 33 from IPython.testing.skipdoctest import skip_doctest
34 34 from IPython.utils.openpy import source_to_unicode
35 35 from IPython.utils.path import unquote_filename
36 36 from IPython.utils.process import abbrev_cwd
37 37 from IPython.utils.terminal import set_term_title
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Magic implementation classes
41 41 #-----------------------------------------------------------------------------
42 42 @magics_class
43 43 class OSMagics(Magics):
44 44 """Magics to interact with the underlying OS (shell-type functionality).
45 45 """
46 46
47 47 @skip_doctest
48 48 @line_magic
49 49 def alias(self, parameter_s=''):
50 50 """Define an alias for a system command.
51 51
52 52 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
53 53
54 54 Then, typing 'alias_name params' will execute the system command 'cmd
55 55 params' (from your underlying operating system).
56 56
57 57 Aliases have lower precedence than magic functions and Python normal
58 58 variables, so if 'foo' is both a Python variable and an alias, the
59 59 alias can not be executed until 'del foo' removes the Python variable.
60 60
61 61 You can use the %l specifier in an alias definition to represent the
62 62 whole line when the alias is called. For example::
63 63
64 64 In [2]: alias bracket echo "Input in brackets: <%l>"
65 65 In [3]: bracket hello world
66 66 Input in brackets: <hello world>
67 67
68 68 You can also define aliases with parameters using %s specifiers (one
69 69 per parameter)::
70 70
71 71 In [1]: alias parts echo first %s second %s
72 72 In [2]: %parts A B
73 73 first A second B
74 74 In [3]: %parts A
75 75 Incorrect number of arguments: 2 expected.
76 76 parts is an alias to: 'echo first %s second %s'
77 77
78 78 Note that %l and %s are mutually exclusive. You can only use one or
79 79 the other in your aliases.
80 80
81 81 Aliases expand Python variables just like system calls using ! or !!
82 82 do: all expressions prefixed with '$' get expanded. For details of
83 83 the semantic rules, see PEP-215:
84 84 http://www.python.org/peps/pep-0215.html. This is the library used by
85 85 IPython for variable expansion. If you want to access a true shell
86 86 variable, an extra $ is necessary to prevent its expansion by
87 87 IPython::
88 88
89 89 In [6]: alias show echo
90 90 In [7]: PATH='A Python string'
91 91 In [8]: show $PATH
92 92 A Python string
93 93 In [9]: show $$PATH
94 94 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
95 95
96 96 You can use the alias facility to acess all of $PATH. See the %rehash
97 97 and %rehashx functions, which automatically create aliases for the
98 98 contents of your $PATH.
99 99
100 100 If called with no parameters, %alias prints the current alias table."""
101 101
102 102 par = parameter_s.strip()
103 103 if not par:
104 104 aliases = sorted(self.shell.alias_manager.aliases)
105 105 # stored = self.shell.db.get('stored_aliases', {} )
106 106 # for k, v in stored:
107 107 # atab.append(k, v[0])
108 108
109 109 print "Total number of aliases:", len(aliases)
110 110 sys.stdout.flush()
111 111 return aliases
112 112
113 113 # Now try to define a new one
114 114 try:
115 115 alias,cmd = par.split(None, 1)
116 116 except:
117 117 print oinspect.getdoc(self.alias)
118 118 else:
119 119 self.shell.alias_manager.soft_define_alias(alias, cmd)
120 120 # end magic_alias
121 121
122 122 @line_magic
123 123 def unalias(self, parameter_s=''):
124 124 """Remove an alias"""
125 125
126 126 aname = parameter_s.strip()
127 127 self.shell.alias_manager.undefine_alias(aname)
128 128 stored = self.shell.db.get('stored_aliases', {} )
129 129 if aname in stored:
130 130 print "Removing %stored alias",aname
131 131 del stored[aname]
132 132 self.shell.db['stored_aliases'] = stored
133 133
134 134 @line_magic
135 135 def rehashx(self, parameter_s=''):
136 136 """Update the alias table with all executable files in $PATH.
137 137
138 138 This version explicitly checks that every entry in $PATH is a file
139 139 with execute access (os.X_OK), so it is much slower than %rehash.
140 140
141 141 Under Windows, it checks executability as a match against a
142 142 '|'-separated string of extensions, stored in the IPython config
143 143 variable win_exec_ext. This defaults to 'exe|com|bat'.
144 144
145 145 This function also resets the root module cache of module completer,
146 146 used on slow filesystems.
147 147 """
148 148 from IPython.core.alias import InvalidAliasError
149 149
150 150 # for the benefit of module completer in ipy_completers.py
151 151 del self.shell.db['rootmodules']
152 152
153 153 path = [os.path.abspath(os.path.expanduser(p)) for p in
154 154 os.environ.get('PATH','').split(os.pathsep)]
155 155 path = filter(os.path.isdir,path)
156 156
157 157 syscmdlist = []
158 158 # Now define isexec in a cross platform manner.
159 159 if os.name == 'posix':
160 160 isexec = lambda fname:os.path.isfile(fname) and \
161 161 os.access(fname,os.X_OK)
162 162 else:
163 163 try:
164 164 winext = os.environ['pathext'].replace(';','|').replace('.','')
165 165 except KeyError:
166 166 winext = 'exe|com|bat|py'
167 167 if 'py' not in winext:
168 168 winext += '|py'
169 169 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
170 170 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
171 171 savedir = os.getcwdu()
172 172
173 173 # Now walk the paths looking for executables to alias.
174 174 try:
175 175 # write the whole loop for posix/Windows so we don't have an if in
176 176 # the innermost part
177 177 if os.name == 'posix':
178 178 for pdir in path:
179 179 os.chdir(pdir)
180 180 for ff in os.listdir(pdir):
181 181 if isexec(ff):
182 182 try:
183 183 # Removes dots from the name since ipython
184 184 # will assume names with dots to be python.
185 185 self.shell.alias_manager.define_alias(
186 186 ff.replace('.',''), ff)
187 187 except InvalidAliasError:
188 188 pass
189 189 else:
190 190 syscmdlist.append(ff)
191 191 else:
192 192 no_alias = self.shell.alias_manager.no_alias
193 193 for pdir in path:
194 194 os.chdir(pdir)
195 195 for ff in os.listdir(pdir):
196 196 base, ext = os.path.splitext(ff)
197 197 if isexec(ff) and base.lower() not in no_alias:
198 198 if ext.lower() == '.exe':
199 199 ff = base
200 200 try:
201 201 # Removes dots from the name since ipython
202 202 # will assume names with dots to be python.
203 203 self.shell.alias_manager.define_alias(
204 204 base.lower().replace('.',''), ff)
205 205 except InvalidAliasError:
206 206 pass
207 207 syscmdlist.append(ff)
208 208 self.shell.db['syscmdlist'] = syscmdlist
209 209 finally:
210 210 os.chdir(savedir)
211 211
212 212 @skip_doctest
213 213 @line_magic
214 214 def pwd(self, parameter_s=''):
215 215 """Return the current working directory path.
216 216
217 217 Examples
218 218 --------
219 219 ::
220 220
221 221 In [9]: pwd
222 222 Out[9]: '/home/tsuser/sprint/ipython'
223 223 """
224 224 return os.getcwdu()
225 225
226 226 @skip_doctest
227 227 @line_magic
228 228 def cd(self, parameter_s=''):
229 229 """Change the current working directory.
230 230
231 231 This command automatically maintains an internal list of directories
232 232 you visit during your IPython session, in the variable _dh. The
233 233 command %dhist shows this history nicely formatted. You can also
234 234 do 'cd -<tab>' to see directory history conveniently.
235 235
236 236 Usage:
237 237
238 238 cd 'dir': changes to directory 'dir'.
239 239
240 240 cd -: changes to the last visited directory.
241 241
242 242 cd -<n>: changes to the n-th directory in the directory history.
243 243
244 244 cd --foo: change to directory that matches 'foo' in history
245 245
246 246 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
247 247 (note: cd <bookmark_name> is enough if there is no
248 248 directory <bookmark_name>, but a bookmark with the name exists.)
249 249 'cd -b <tab>' allows you to tab-complete bookmark names.
250 250
251 251 Options:
252 252
253 253 -q: quiet. Do not print the working directory after the cd command is
254 254 executed. By default IPython's cd command does print this directory,
255 255 since the default prompts do not display path information.
256 256
257 257 Note that !cd doesn't work for this purpose because the shell where
258 258 !command runs is immediately discarded after executing 'command'.
259 259
260 260 Examples
261 261 --------
262 262 ::
263 263
264 264 In [10]: cd parent/child
265 265 /home/tsuser/parent/child
266 266 """
267 267
268 268 oldcwd = os.getcwdu()
269 269 numcd = re.match(r'(-)(\d+)$',parameter_s)
270 270 # jump in directory history by number
271 271 if numcd:
272 272 nn = int(numcd.group(2))
273 273 try:
274 274 ps = self.shell.user_ns['_dh'][nn]
275 275 except IndexError:
276 276 print 'The requested directory does not exist in history.'
277 277 return
278 278 else:
279 279 opts = {}
280 280 elif parameter_s.startswith('--'):
281 281 ps = None
282 282 fallback = None
283 283 pat = parameter_s[2:]
284 284 dh = self.shell.user_ns['_dh']
285 285 # first search only by basename (last component)
286 286 for ent in reversed(dh):
287 287 if pat in os.path.basename(ent) and os.path.isdir(ent):
288 288 ps = ent
289 289 break
290 290
291 291 if fallback is None and pat in ent and os.path.isdir(ent):
292 292 fallback = ent
293 293
294 294 # if we have no last part match, pick the first full path match
295 295 if ps is None:
296 296 ps = fallback
297 297
298 298 if ps is None:
299 299 print "No matching entry in directory history"
300 300 return
301 301 else:
302 302 opts = {}
303 303
304 304
305 305 else:
306 306 #turn all non-space-escaping backslashes to slashes,
307 307 # for c:\windows\directory\names\
308 308 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
309 309 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
310 310 # jump to previous
311 311 if ps == '-':
312 312 try:
313 313 ps = self.shell.user_ns['_dh'][-2]
314 314 except IndexError:
315 315 raise UsageError('%cd -: No previous directory to change to.')
316 316 # jump to bookmark if needed
317 317 else:
318 318 if not os.path.isdir(ps) or 'b' in opts:
319 319 bkms = self.shell.db.get('bookmarks', {})
320 320
321 321 if ps in bkms:
322 322 target = bkms[ps]
323 323 print '(bookmark:%s) -> %s' % (ps, target)
324 324 ps = target
325 325 else:
326 326 if 'b' in opts:
327 327 raise UsageError("Bookmark '%s' not found. "
328 328 "Use '%%bookmark -l' to see your bookmarks." % ps)
329 329
330 330 # strip extra quotes on Windows, because os.chdir doesn't like them
331 331 ps = unquote_filename(ps)
332 332 # at this point ps should point to the target dir
333 333 if ps:
334 334 try:
335 335 os.chdir(os.path.expanduser(ps))
336 336 if hasattr(self.shell, 'term_title') and self.shell.term_title:
337 337 set_term_title('IPython: ' + abbrev_cwd())
338 338 except OSError:
339 339 print sys.exc_info()[1]
340 340 else:
341 341 cwd = os.getcwdu()
342 342 dhist = self.shell.user_ns['_dh']
343 343 if oldcwd != cwd:
344 344 dhist.append(cwd)
345 345 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
346 346
347 347 else:
348 348 os.chdir(self.shell.home_dir)
349 349 if hasattr(self.shell, 'term_title') and self.shell.term_title:
350 350 set_term_title('IPython: ' + '~')
351 351 cwd = os.getcwdu()
352 352 dhist = self.shell.user_ns['_dh']
353 353
354 354 if oldcwd != cwd:
355 355 dhist.append(cwd)
356 356 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
357 357 if not 'q' in opts and self.shell.user_ns['_dh']:
358 358 print self.shell.user_ns['_dh'][-1]
359 359
360 360
361 361 @line_magic
362 362 def env(self, parameter_s=''):
363 363 """List environment variables."""
364 364
365 365 return dict(os.environ)
366 366
367 367 @line_magic
368 368 def pushd(self, parameter_s=''):
369 369 """Place the current dir on stack and change directory.
370 370
371 371 Usage:\\
372 372 %pushd ['dirname']
373 373 """
374 374
375 375 dir_s = self.shell.dir_stack
376 376 tgt = os.path.expanduser(unquote_filename(parameter_s))
377 377 cwd = os.getcwdu().replace(self.shell.home_dir,'~')
378 378 if tgt:
379 379 self.cd(parameter_s)
380 380 dir_s.insert(0,cwd)
381 381 return self.shell.magic('dirs')
382 382
383 383 @line_magic
384 384 def popd(self, parameter_s=''):
385 385 """Change to directory popped off the top of the stack.
386 386 """
387 387 if not self.shell.dir_stack:
388 388 raise UsageError("%popd on empty stack")
389 389 top = self.shell.dir_stack.pop(0)
390 390 self.cd(top)
391 391 print "popd ->",top
392 392
393 393 @line_magic
394 394 def dirs(self, parameter_s=''):
395 395 """Return the current directory stack."""
396 396
397 397 return self.shell.dir_stack
398 398
399 399 @line_magic
400 400 def dhist(self, parameter_s=''):
401 401 """Print your history of visited directories.
402 402
403 403 %dhist -> print full history\\
404 404 %dhist n -> print last n entries only\\
405 405 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
406 406
407 407 This history is automatically maintained by the %cd command, and
408 408 always available as the global list variable _dh. You can use %cd -<n>
409 409 to go to directory number <n>.
410 410
411 411 Note that most of time, you should view directory history by entering
412 412 cd -<TAB>.
413 413
414 414 """
415 415
416 416 dh = self.shell.user_ns['_dh']
417 417 if parameter_s:
418 418 try:
419 419 args = map(int,parameter_s.split())
420 420 except:
421 421 self.arg_err(self.dhist)
422 422 return
423 423 if len(args) == 1:
424 424 ini,fin = max(len(dh)-(args[0]),0),len(dh)
425 425 elif len(args) == 2:
426 426 ini,fin = args
427 427 fin = min(fin, len(dh))
428 428 else:
429 429 self.arg_err(self.dhist)
430 430 return
431 431 else:
432 432 ini,fin = 0,len(dh)
433 433 print 'Directory history (kept in _dh)'
434 434 for i in range(ini, fin):
435 435 print "%d: %s" % (i, dh[i])
436 436
437 437 @skip_doctest
438 438 @line_magic
439 439 def sc(self, parameter_s=''):
440 440 """Shell capture - run shell command and capture output (DEPRECATED use !).
441 441
442 442 DEPRECATED. Suboptimal, retained for backwards compatibility.
443 443
444 444 You should use the form 'var = !command' instead. Example:
445 445
446 446 "%sc -l myfiles = ls ~" should now be written as
447 447
448 448 "myfiles = !ls ~"
449 449
450 450 myfiles.s, myfiles.l and myfiles.n still apply as documented
451 451 below.
452 452
453 453 --
454 454 %sc [options] varname=command
455 455
456 456 IPython will run the given command using commands.getoutput(), and
457 457 will then update the user's interactive namespace with a variable
458 458 called varname, containing the value of the call. Your command can
459 459 contain shell wildcards, pipes, etc.
460 460
461 461 The '=' sign in the syntax is mandatory, and the variable name you
462 462 supply must follow Python's standard conventions for valid names.
463 463
464 464 (A special format without variable name exists for internal use)
465 465
466 466 Options:
467 467
468 468 -l: list output. Split the output on newlines into a list before
469 469 assigning it to the given variable. By default the output is stored
470 470 as a single string.
471 471
472 472 -v: verbose. Print the contents of the variable.
473 473
474 474 In most cases you should not need to split as a list, because the
475 475 returned value is a special type of string which can automatically
476 476 provide its contents either as a list (split on newlines) or as a
477 477 space-separated string. These are convenient, respectively, either
478 478 for sequential processing or to be passed to a shell command.
479 479
480 480 For example::
481 481
482 482 # Capture into variable a
483 483 In [1]: sc a=ls *py
484 484
485 485 # a is a string with embedded newlines
486 486 In [2]: a
487 487 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
488 488
489 489 # which can be seen as a list:
490 490 In [3]: a.l
491 491 Out[3]: ['setup.py', 'win32_manual_post_install.py']
492 492
493 493 # or as a whitespace-separated string:
494 494 In [4]: a.s
495 495 Out[4]: 'setup.py win32_manual_post_install.py'
496 496
497 497 # a.s is useful to pass as a single command line:
498 498 In [5]: !wc -l $a.s
499 499 146 setup.py
500 500 130 win32_manual_post_install.py
501 501 276 total
502 502
503 503 # while the list form is useful to loop over:
504 504 In [6]: for f in a.l:
505 505 ...: !wc -l $f
506 506 ...:
507 507 146 setup.py
508 508 130 win32_manual_post_install.py
509 509
510 510 Similarly, the lists returned by the -l option are also special, in
511 511 the sense that you can equally invoke the .s attribute on them to
512 512 automatically get a whitespace-separated string from their contents::
513 513
514 514 In [7]: sc -l b=ls *py
515 515
516 516 In [8]: b
517 517 Out[8]: ['setup.py', 'win32_manual_post_install.py']
518 518
519 519 In [9]: b.s
520 520 Out[9]: 'setup.py win32_manual_post_install.py'
521 521
522 522 In summary, both the lists and strings used for output capture have
523 523 the following special attributes::
524 524
525 525 .l (or .list) : value as list.
526 526 .n (or .nlstr): value as newline-separated string.
527 527 .s (or .spstr): value as space-separated string.
528 528 """
529 529
530 530 opts,args = self.parse_options(parameter_s, 'lv')
531 531 # Try to get a variable name and command to run
532 532 try:
533 533 # the variable name must be obtained from the parse_options
534 534 # output, which uses shlex.split to strip options out.
535 535 var,_ = args.split('=', 1)
536 536 var = var.strip()
537 537 # But the command has to be extracted from the original input
538 538 # parameter_s, not on what parse_options returns, to avoid the
539 539 # quote stripping which shlex.split performs on it.
540 540 _,cmd = parameter_s.split('=', 1)
541 541 except ValueError:
542 542 var,cmd = '',''
543 543 # If all looks ok, proceed
544 544 split = 'l' in opts
545 545 out = self.shell.getoutput(cmd, split=split)
546 546 if 'v' in opts:
547 547 print '%s ==\n%s' % (var, pformat(out))
548 548 if var:
549 549 self.shell.user_ns.update({var:out})
550 550 else:
551 551 return out
552 552
553 553 @line_cell_magic
554 554 def sx(self, line='', cell=None):
555 555 """Shell execute - run shell command and capture output (!! is short-hand).
556 556
557 557 %sx command
558 558
559 559 IPython will run the given command using commands.getoutput(), and
560 560 return the result formatted as a list (split on '\\n'). Since the
561 561 output is _returned_, it will be stored in ipython's regular output
562 562 cache Out[N] and in the '_N' automatic variables.
563 563
564 564 Notes:
565 565
566 566 1) If an input line begins with '!!', then %sx is automatically
567 567 invoked. That is, while::
568 568
569 569 !ls
570 570
571 571 causes ipython to simply issue system('ls'), typing::
572 572
573 573 !!ls
574 574
575 575 is a shorthand equivalent to::
576 576
577 577 %sx ls
578 578
579 579 2) %sx differs from %sc in that %sx automatically splits into a list,
580 580 like '%sc -l'. The reason for this is to make it as easy as possible
581 581 to process line-oriented shell output via further python commands.
582 582 %sc is meant to provide much finer control, but requires more
583 583 typing.
584 584
585 585 3) Just like %sc -l, this is a list with special attributes:
586 586 ::
587 587
588 588 .l (or .list) : value as list.
589 589 .n (or .nlstr): value as newline-separated string.
590 590 .s (or .spstr): value as whitespace-separated string.
591 591
592 592 This is very useful when trying to use such lists as arguments to
593 593 system commands."""
594 594
595 595 if cell is None:
596 596 # line magic
597 597 return self.shell.getoutput(line)
598 598 else:
599 599 opts,args = self.parse_options(line, '', 'out=')
600 600 output = self.shell.getoutput(cell)
601 601 out_name = opts.get('out', opts.get('o'))
602 602 if out_name:
603 603 self.shell.user_ns[out_name] = output
604 604 else:
605 605 return output
606 606
607 607 system = line_cell_magic('system')(sx)
608 608 bang = cell_magic('!')(sx)
609 609
610 610 @line_magic
611 611 def bookmark(self, parameter_s=''):
612 612 """Manage IPython's bookmark system.
613 613
614 614 %bookmark <name> - set bookmark to current dir
615 615 %bookmark <name> <dir> - set bookmark to <dir>
616 616 %bookmark -l - list all bookmarks
617 617 %bookmark -d <name> - remove bookmark
618 618 %bookmark -r - remove all bookmarks
619 619
620 620 You can later on access a bookmarked folder with::
621 621
622 622 %cd -b <name>
623 623
624 624 or simply '%cd <name>' if there is no directory called <name> AND
625 625 there is such a bookmark defined.
626 626
627 627 Your bookmarks persist through IPython sessions, but they are
628 628 associated with each profile."""
629 629
630 630 opts,args = self.parse_options(parameter_s,'drl',mode='list')
631 631 if len(args) > 2:
632 632 raise UsageError("%bookmark: too many arguments")
633 633
634 634 bkms = self.shell.db.get('bookmarks',{})
635 635
636 636 if 'd' in opts:
637 637 try:
638 638 todel = args[0]
639 639 except IndexError:
640 640 raise UsageError(
641 641 "%bookmark -d: must provide a bookmark to delete")
642 642 else:
643 643 try:
644 644 del bkms[todel]
645 645 except KeyError:
646 646 raise UsageError(
647 647 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
648 648
649 649 elif 'r' in opts:
650 650 bkms = {}
651 651 elif 'l' in opts:
652 652 bks = bkms.keys()
653 653 bks.sort()
654 654 if bks:
655 655 size = max(map(len, bks))
656 656 else:
657 657 size = 0
658 658 fmt = '%-'+str(size)+'s -> %s'
659 659 print 'Current bookmarks:'
660 660 for bk in bks:
661 661 print fmt % (bk, bkms[bk])
662 662 else:
663 663 if not args:
664 664 raise UsageError("%bookmark: You must specify the bookmark name")
665 665 elif len(args)==1:
666 666 bkms[args[0]] = os.getcwdu()
667 667 elif len(args)==2:
668 668 bkms[args[0]] = args[1]
669 669 self.shell.db['bookmarks'] = bkms
670 670
671 671 @line_magic
672 672 def pycat(self, parameter_s=''):
673 673 """Show a syntax-highlighted file through a pager.
674 674
675 675 This magic is similar to the cat utility, but it will assume the file
676 676 to be Python source and will show it with syntax highlighting.
677 677
678 678 This magic command can either take a local filename, an url,
679 679 an history range (see %history) or a macro as argument ::
680 680
681 681 %pycat myscript.py
682 682 %pycat 7-27
683 683 %pycat myMacro
684 684 %pycat http://www.example.com/myscript.py
685 685 """
686 686 if not parameter_s:
687 687 raise UsageError('Missing filename, URL, input history range, '
688 688 'or macro.')
689 689
690 690 try :
691 691 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
692 692 except (ValueError, IOError):
693 693 print "Error: no such file, variable, URL, history range or macro"
694 694 return
695 695
696 696 page.page(self.shell.pycolorize(source_to_unicode(cont)))
697 697
698 698 @magic_arguments.magic_arguments()
699 699 @magic_arguments.argument(
700 700 '-a', '--amend', action='store_true', default=False,
701 701 help='Open file for amending if it exists'
702 702 )
703 703 @magic_arguments.argument(
704 704 'filename', type=unicode,
705 705 help='file to write'
706 706 )
707 707 @cell_magic
708 708 def file(self, line, cell):
709 709 """Write the contents of the cell to a file.
710 710
711 711 For frontends that do not support stdin (Notebook), -f is implied.
712 712 """
713 713 args = magic_arguments.parse_argstring(self.file, line)
714 filename = unquote_filename(args.filename)
714 filename = os.path.expanduser(unquote_filename(args.filename))
715 715
716 716 if os.path.exists(filename):
717 717 if args.amend:
718 718 print "Amending to %s" % filename
719 719 else:
720 720 print "Overwriting %s" % filename
721 721 else:
722 722 print "Writing %s" % filename
723 723
724 724 mode = 'a' if args.amend else 'w'
725 725 with io.open(filename, mode, encoding='utf-8') as f:
726 726 f.write(cell)
General Comments 0
You need to be logged in to leave comments. Login now