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