Show More
@@ -0,0 +1,50 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # encoding: utf-8 | |||
|
3 | """ | |||
|
4 | A payload based version of page. | |||
|
5 | ||||
|
6 | Authors: | |||
|
7 | ||||
|
8 | * Brian Granger | |||
|
9 | * Fernando Perez | |||
|
10 | """ | |||
|
11 | ||||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | # Copyright (C) 2008-2010 The IPython Development Team | |||
|
14 | # | |||
|
15 | # Distributed under the terms of the BSD License. The full license is in | |||
|
16 | # the file COPYING, distributed as part of this software. | |||
|
17 | #----------------------------------------------------------------------------- | |||
|
18 | ||||
|
19 | #----------------------------------------------------------------------------- | |||
|
20 | # Imports | |||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | ||||
|
23 | from IPython.core.interactiveshell import InteractiveShell | |||
|
24 | ||||
|
25 | #----------------------------------------------------------------------------- | |||
|
26 | # Classes and functions | |||
|
27 | #----------------------------------------------------------------------------- | |||
|
28 | ||||
|
29 | def page(strng, start=0, screen_lines=0, pager_cmd=None): | |||
|
30 | """Print a string, piping through a pager. | |||
|
31 | ||||
|
32 | This version ignores the screen_lines and pager_cmd arguments and uses | |||
|
33 | IPython's payload system instead. | |||
|
34 | """ | |||
|
35 | ||||
|
36 | # Some routines may auto-compute start offsets incorrectly and pass a | |||
|
37 | # negative value. Offset to 0 for robustness. | |||
|
38 | start = max(0, start) | |||
|
39 | shell = InteractiveShell.instance() | |||
|
40 | payload = dict( | |||
|
41 | source='IPython.zmq.page.page', | |||
|
42 | data=strng, | |||
|
43 | start_line_number=start | |||
|
44 | ) | |||
|
45 | shell.payload_manager.write_payload(payload) | |||
|
46 | ||||
|
47 | def install_payload_page(): | |||
|
48 | """Install this version of page as IPython.core.page.page.""" | |||
|
49 | from IPython.core import page as corepage | |||
|
50 | corepage.page = page |
@@ -1901,9 +1901,6 b' class InteractiveShell(Configurable, Magic):' | |||||
1901 | - 1: an error occurred. |
|
1901 | - 1: an error occurred. | |
1902 | """ |
|
1902 | """ | |
1903 |
|
1903 | |||
1904 | # Clear the payload before executing new code. |
|
|||
1905 | self.payload_manager.clear_payload() |
|
|||
1906 |
|
||||
1907 | # Set our own excepthook in case the user code tries to call it |
|
1904 | # Set our own excepthook in case the user code tries to call it | |
1908 | # directly, so that the IPython crash handler doesn't get triggered |
|
1905 | # directly, so that the IPython crash handler doesn't get triggered | |
1909 | old_excepthook,sys.excepthook = sys.excepthook, self.excepthook |
|
1906 | old_excepthook,sys.excepthook = sys.excepthook, self.excepthook |
@@ -52,7 +52,7 b' from IPython.core.error import TryNext' | |||||
52 | from IPython.core.error import UsageError |
|
52 | from IPython.core.error import UsageError | |
53 | from IPython.core.fakemodule import FakeModule |
|
53 | from IPython.core.fakemodule import FakeModule | |
54 | from IPython.core.macro import Macro |
|
54 | from IPython.core.macro import Macro | |
55 |
from IPython.core |
|
55 | from IPython.core import page | |
56 | from IPython.core.prefilter import ESC_MAGIC |
|
56 | from IPython.core.prefilter import ESC_MAGIC | |
57 | from IPython.lib.pylabtools import mpl_runner |
|
57 | from IPython.lib.pylabtools import mpl_runner | |
58 | from IPython.lib.inputhook import enable_gui |
|
58 | from IPython.lib.inputhook import enable_gui | |
@@ -514,7 +514,7 b' Currently the magic system has the following functions:\\n"""' | |||||
514 | (' '+mesc).join(self.lsmagic()), |
|
514 | (' '+mesc).join(self.lsmagic()), | |
515 | Magic.auto_status[self.shell.automagic] ) ) |
|
515 | Magic.auto_status[self.shell.automagic] ) ) | |
516 |
|
516 | |||
517 | page(outmsg,screen_lines=self.shell.usable_screen_length) |
|
517 | page.page(outmsg,screen_lines=self.shell.usable_screen_length) | |
518 |
|
518 | |||
519 |
|
519 | |||
520 | def magic_autoindent(self, parameter_s = ''): |
|
520 | def magic_autoindent(self, parameter_s = ''): | |
@@ -656,7 +656,7 b' Currently the magic system has the following functions:\\n"""' | |||||
656 | info = self._ofind(oname) |
|
656 | info = self._ofind(oname) | |
657 | if info['found']: |
|
657 | if info['found']: | |
658 | txt = (raw and str or pformat)( info['obj'] ) |
|
658 | txt = (raw and str or pformat)( info['obj'] ) | |
659 | page(txt) |
|
659 | page.page(txt) | |
660 | else: |
|
660 | else: | |
661 | print 'Object `%s` not found' % oname |
|
661 | print 'Object `%s` not found' % oname | |
662 |
|
662 | |||
@@ -727,7 +727,7 b' Currently the magic system has the following functions:\\n"""' | |||||
727 | except IOError,msg: |
|
727 | except IOError,msg: | |
728 | print msg |
|
728 | print msg | |
729 | return |
|
729 | return | |
730 | page(self.shell.inspector.format(file(filename).read())) |
|
730 | page.page(self.shell.inspector.format(file(filename).read())) | |
731 |
|
731 | |||
732 | def _inspect(self,meth,oname,namespaces=None,**kw): |
|
732 | def _inspect(self,meth,oname,namespaces=None,**kw): | |
733 | """Generic interface to the inspector system. |
|
733 | """Generic interface to the inspector system. | |
@@ -1520,7 +1520,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1520 | output = stdout_trap.getvalue() |
|
1520 | output = stdout_trap.getvalue() | |
1521 | output = output.rstrip() |
|
1521 | output = output.rstrip() | |
1522 |
|
1522 | |||
1523 | page(output,screen_lines=self.shell.usable_screen_length) |
|
1523 | page.page(output,screen_lines=self.shell.usable_screen_length) | |
1524 | print sys_exit, |
|
1524 | print sys_exit, | |
1525 |
|
1525 | |||
1526 | dump_file = opts.D[0] |
|
1526 | dump_file = opts.D[0] | |
@@ -3256,7 +3256,7 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3256 | print "Error: no such file or variable" |
|
3256 | print "Error: no such file or variable" | |
3257 | return |
|
3257 | return | |
3258 |
|
3258 | |||
3259 | page(self.shell.pycolorize(cont), |
|
3259 | page.page(self.shell.pycolorize(cont), | |
3260 | screen_lines=self.shell.usable_screen_length) |
|
3260 | screen_lines=self.shell.usable_screen_length) | |
3261 |
|
3261 | |||
3262 | def _rerun_pasted(self): |
|
3262 | def _rerun_pasted(self): | |
@@ -3413,7 +3413,7 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3413 | import IPython.core.usage |
|
3413 | import IPython.core.usage | |
3414 | qr = IPython.core.usage.quick_reference + self.magic_magic('-brief') |
|
3414 | qr = IPython.core.usage.quick_reference + self.magic_magic('-brief') | |
3415 |
|
3415 | |||
3416 | page(qr) |
|
3416 | page.page(qr) | |
3417 |
|
3417 | |||
3418 | def magic_doctest_mode(self,parameter_s=''): |
|
3418 | def magic_doctest_mode(self,parameter_s=''): | |
3419 | """Toggle doctest mode on and off. |
|
3419 | """Toggle doctest mode on and off. |
@@ -27,7 +27,7 b' import sys' | |||||
27 | import types |
|
27 | import types | |
28 |
|
28 | |||
29 | # IPython's own |
|
29 | # IPython's own | |
30 |
from IPython.core |
|
30 | from IPython.core import page | |
31 | from IPython.external.Itpl import itpl |
|
31 | from IPython.external.Itpl import itpl | |
32 | from IPython.utils import PyColorize |
|
32 | from IPython.utils import PyColorize | |
33 | import IPython.utils.io |
|
33 | import IPython.utils.io | |
@@ -281,7 +281,7 b' class Inspector:' | |||||
281 | if output is None: |
|
281 | if output is None: | |
282 | self.noinfo('documentation',oname) |
|
282 | self.noinfo('documentation',oname) | |
283 | return |
|
283 | return | |
284 | page(output) |
|
284 | page.page(output) | |
285 |
|
285 | |||
286 | def psource(self,obj,oname=''): |
|
286 | def psource(self,obj,oname=''): | |
287 | """Print the source code for an object.""" |
|
287 | """Print the source code for an object.""" | |
@@ -293,7 +293,7 b' class Inspector:' | |||||
293 | except: |
|
293 | except: | |
294 | self.noinfo('source',oname) |
|
294 | self.noinfo('source',oname) | |
295 | else: |
|
295 | else: | |
296 | page(self.format(src)) |
|
296 | page.page(self.format(src)) | |
297 |
|
297 | |||
298 | def pfile(self,obj,oname=''): |
|
298 | def pfile(self,obj,oname=''): | |
299 | """Show the whole file where an object was defined.""" |
|
299 | """Show the whole file where an object was defined.""" | |
@@ -325,7 +325,7 b' class Inspector:' | |||||
325 | # Print only text files, not extension binaries. Note that |
|
325 | # Print only text files, not extension binaries. Note that | |
326 | # getsourcelines returns lineno with 1-offset and page() uses |
|
326 | # getsourcelines returns lineno with 1-offset and page() uses | |
327 | # 0-offset, so we must adjust. |
|
327 | # 0-offset, so we must adjust. | |
328 | page(self.format(open(ofile).read()),lineno-1) |
|
328 | page.page(self.format(open(ofile).read()),lineno-1) | |
329 |
|
329 | |||
330 | def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0): |
|
330 | def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0): | |
331 | """Show detailed information about an object. |
|
331 | """Show detailed information about an object. | |
@@ -548,7 +548,7 b' class Inspector:' | |||||
548 | # Finally send to printer/pager |
|
548 | # Finally send to printer/pager | |
549 | output = out.getvalue() |
|
549 | output = out.getvalue() | |
550 | if output: |
|
550 | if output: | |
551 | page(output) |
|
551 | page.page(output) | |
552 | # end pinfo |
|
552 | # end pinfo | |
553 |
|
553 | |||
554 | def psearch(self,pattern,ns_table,ns_search=[], |
|
554 | def psearch(self,pattern,ns_table,ns_search=[], | |
@@ -606,4 +606,4 b' class Inspector:' | |||||
606 | search_result.extend(tmp_res) |
|
606 | search_result.extend(tmp_res) | |
607 | search_result.sort() |
|
607 | search_result.sort() | |
608 |
|
608 | |||
609 | page('\n'.join(search_result)) |
|
609 | page.page('\n'.join(search_result)) |
@@ -33,7 +33,7 b' from IPython.core.alias import AliasManager' | |||||
33 | from IPython.core.autocall import IPyAutocall |
|
33 | from IPython.core.autocall import IPyAutocall | |
34 | from IPython.config.configurable import Configurable |
|
34 | from IPython.config.configurable import Configurable | |
35 | from IPython.core.splitinput import split_user_input |
|
35 | from IPython.core.splitinput import split_user_input | |
36 |
from IPython.core |
|
36 | from IPython.core import page | |
37 |
|
37 | |||
38 | from IPython.utils.traitlets import List, Int, Any, Str, CBool, Bool, Instance |
|
38 | from IPython.utils.traitlets import List, Int, Any, Str, CBool, Bool, Instance | |
39 | import IPython.utils.io |
|
39 | import IPython.utils.io | |
@@ -960,7 +960,7 b' class HelpHandler(PrefilterHandler):' | |||||
960 | #print 'line:<%r>' % line # dbg |
|
960 | #print 'line:<%r>' % line # dbg | |
961 | self.shell.magic_pinfo(line) |
|
961 | self.shell.magic_pinfo(line) | |
962 | else: |
|
962 | else: | |
963 | page(self.shell.usage, screen_lines=self.shell.usable_screen_length) |
|
963 | page.page(self.shell.usage, screen_lines=self.shell.usable_screen_length) | |
964 | return '' # Empty string is needed here! |
|
964 | return '' # Empty string is needed here! | |
965 | except: |
|
965 | except: | |
966 | raise |
|
966 | raise |
@@ -17,7 +17,7 b" __all__ = ['Gnuplot','gp','gp_new','plot','plot2','splot','replot'," | |||||
17 |
|
17 | |||
18 | import IPython.GnuplotRuntime as GRun |
|
18 | import IPython.GnuplotRuntime as GRun | |
19 | from IPython.utils.genutils import warn |
|
19 | from IPython.utils.genutils import warn | |
20 |
from IPython.core |
|
20 | from IPython.core import page | |
21 |
|
21 | |||
22 | # Set global names for interactive use |
|
22 | # Set global names for interactive use | |
23 | Gnuplot = GRun.Gnuplot |
|
23 | Gnuplot = GRun.Gnuplot |
@@ -1,3 +1,5 b'' | |||||
|
1 | import os | |||
|
2 | ||||
1 | # System library imports |
|
3 | # System library imports | |
2 | from PyQt4 import QtCore, QtGui |
|
4 | from PyQt4 import QtCore, QtGui | |
3 |
|
5 | |||
@@ -61,7 +63,7 b' class RichIPythonWidget(IPythonWidget):' | |||||
61 | """ |
|
63 | """ | |
62 | payload = msg['content']['payload'] |
|
64 | payload = msg['content']['payload'] | |
63 | for item in payload: |
|
65 | for item in payload: | |
64 | if item['type'] == 'plot': |
|
66 | if item['source'] == 'IPython.zmq.pylab.backend_payload.add_plot_payload': | |
65 | if item['format'] == 'svg': |
|
67 | if item['format'] == 'svg': | |
66 | svg = item['data'] |
|
68 | svg = item['data'] | |
67 | try: |
|
69 | try: | |
@@ -78,6 +80,28 b' class RichIPythonWidget(IPythonWidget):' | |||||
78 | else: |
|
80 | else: | |
79 | # Add other plot formats here! |
|
81 | # Add other plot formats here! | |
80 | pass |
|
82 | pass | |
|
83 | elif item['source'] == 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic': | |||
|
84 | # TODO: I have implmented the logic for TextMate on the Mac. | |||
|
85 | # But, we need to allow payload handlers on the non-rich | |||
|
86 | # text IPython widget as well. Furthermore, we should probably | |||
|
87 | # move these handlers to separate methods. But, we need to | |||
|
88 | # be very careful to process the payload list in order. Thus, | |||
|
89 | # we will probably need a _handle_payload method of the | |||
|
90 | # base class that dispatches to the separate handler methods | |||
|
91 | # for each payload source. If a particular subclass doesn't | |||
|
92 | # have a handler for a payload source, it should at least | |||
|
93 | # print a nice message. | |||
|
94 | filename = item['filename'] | |||
|
95 | line_number = item['line_number'] | |||
|
96 | if line_number is None: | |||
|
97 | cmd = 'mate %s' % filename | |||
|
98 | else: | |||
|
99 | cmd = 'mate -l %s %s' % (line_number, filename) | |||
|
100 | os.system(cmd) | |||
|
101 | elif item['source'] == 'IPython.zmq.page.page': | |||
|
102 | # TODO: This is probably a good place to start, but Evan can | |||
|
103 | # add better paging capabilities. | |||
|
104 | self._append_plain_text(item['data']) | |||
81 | else: |
|
105 | else: | |
82 | # Add other payload types here! |
|
106 | # Add other payload types here! | |
83 | pass |
|
107 | pass |
@@ -19,5 +19,8 b' def add_plot_payload(format, data, metadata={}):' | |||||
19 | metadata : dict, optional [default empty] |
|
19 | metadata : dict, optional [default empty] | |
20 | Allows for specification of additional information about the plot data. |
|
20 | Allows for specification of additional information about the plot data. | |
21 | """ |
|
21 | """ | |
22 | payload = dict(type='plot', format=format, data=data, metadata=metadata) |
|
22 | payload = dict( | |
|
23 | source='IPython.zmq.pylab.backend_payload.add_plot_payload', | |||
|
24 | format=format, data=data, metadata=metadata | |||
|
25 | ) | |||
23 | InteractiveShell.instance().payload_manager.write_payload(payload) |
|
26 | InteractiveShell.instance().payload_manager.write_payload(payload) |
@@ -1,3 +1,5 b'' | |||||
|
1 | import inspect | |||
|
2 | import re | |||
1 | import sys |
|
3 | import sys | |
2 | from subprocess import Popen, PIPE |
|
4 | from subprocess import Popen, PIPE | |
3 |
|
5 | |||
@@ -5,8 +7,17 b' from IPython.core.interactiveshell import (' | |||||
5 | InteractiveShell, InteractiveShellABC |
|
7 | InteractiveShell, InteractiveShellABC | |
6 | ) |
|
8 | ) | |
7 | from IPython.core.displayhook import DisplayHook |
|
9 | from IPython.core.displayhook import DisplayHook | |
|
10 | from IPython.core.macro import Macro | |||
|
11 | from IPython.utils.path import get_py_filename | |||
|
12 | from IPython.utils.text import StringTypes | |||
8 | from IPython.utils.traitlets import Instance, Type, Dict |
|
13 | from IPython.utils.traitlets import Instance, Type, Dict | |
|
14 | from IPython.utils.warn import warn | |||
9 | from IPython.zmq.session import extract_header |
|
15 | from IPython.zmq.session import extract_header | |
|
16 | from IPython.core.payloadpage import install_payload_page | |||
|
17 | ||||
|
18 | ||||
|
19 | # Install the payload version of page. | |||
|
20 | install_payload_page() | |||
10 |
|
21 | |||
11 |
|
22 | |||
12 | class ZMQDisplayHook(DisplayHook): |
|
23 | class ZMQDisplayHook(DisplayHook): | |
@@ -66,6 +77,282 b' class ZMQInteractiveShell(InteractiveShell):' | |||||
66 | Term = IPython.utils.io.IOTerm() |
|
77 | Term = IPython.utils.io.IOTerm() | |
67 | IPython.utils.io.Term = Term |
|
78 | IPython.utils.io.Term = Term | |
68 |
|
79 | |||
|
80 | def magic_edit(self,parameter_s='',last_call=['','']): | |||
|
81 | """Bring up an editor and execute the resulting code. | |||
|
82 | ||||
|
83 | Usage: | |||
|
84 | %edit [options] [args] | |||
|
85 | ||||
|
86 | %edit runs IPython's editor hook. The default version of this hook is | |||
|
87 | set to call the __IPYTHON__.rc.editor command. This is read from your | |||
|
88 | environment variable $EDITOR. If this isn't found, it will default to | |||
|
89 | vi under Linux/Unix and to notepad under Windows. See the end of this | |||
|
90 | docstring for how to change the editor hook. | |||
|
91 | ||||
|
92 | You can also set the value of this editor via the command line option | |||
|
93 | '-editor' or in your ipythonrc file. This is useful if you wish to use | |||
|
94 | specifically for IPython an editor different from your typical default | |||
|
95 | (and for Windows users who typically don't set environment variables). | |||
|
96 | ||||
|
97 | This command allows you to conveniently edit multi-line code right in | |||
|
98 | your IPython session. | |||
|
99 | ||||
|
100 | If called without arguments, %edit opens up an empty editor with a | |||
|
101 | temporary file and will execute the contents of this file when you | |||
|
102 | close it (don't forget to save it!). | |||
|
103 | ||||
|
104 | ||||
|
105 | Options: | |||
|
106 | ||||
|
107 | -n <number>: open the editor at a specified line number. By default, | |||
|
108 | the IPython editor hook uses the unix syntax 'editor +N filename', but | |||
|
109 | you can configure this by providing your own modified hook if your | |||
|
110 | favorite editor supports line-number specifications with a different | |||
|
111 | syntax. | |||
|
112 | ||||
|
113 | -p: this will call the editor with the same data as the previous time | |||
|
114 | it was used, regardless of how long ago (in your current session) it | |||
|
115 | was. | |||
|
116 | ||||
|
117 | -r: use 'raw' input. This option only applies to input taken from the | |||
|
118 | user's history. By default, the 'processed' history is used, so that | |||
|
119 | magics are loaded in their transformed version to valid Python. If | |||
|
120 | this option is given, the raw input as typed as the command line is | |||
|
121 | used instead. When you exit the editor, it will be executed by | |||
|
122 | IPython's own processor. | |||
|
123 | ||||
|
124 | -x: do not execute the edited code immediately upon exit. This is | |||
|
125 | mainly useful if you are editing programs which need to be called with | |||
|
126 | command line arguments, which you can then do using %run. | |||
|
127 | ||||
|
128 | ||||
|
129 | Arguments: | |||
|
130 | ||||
|
131 | If arguments are given, the following possibilites exist: | |||
|
132 | ||||
|
133 | - The arguments are numbers or pairs of colon-separated numbers (like | |||
|
134 | 1 4:8 9). These are interpreted as lines of previous input to be | |||
|
135 | loaded into the editor. The syntax is the same of the %macro command. | |||
|
136 | ||||
|
137 | - If the argument doesn't start with a number, it is evaluated as a | |||
|
138 | variable and its contents loaded into the editor. You can thus edit | |||
|
139 | any string which contains python code (including the result of | |||
|
140 | previous edits). | |||
|
141 | ||||
|
142 | - If the argument is the name of an object (other than a string), | |||
|
143 | IPython will try to locate the file where it was defined and open the | |||
|
144 | editor at the point where it is defined. You can use `%edit function` | |||
|
145 | to load an editor exactly at the point where 'function' is defined, | |||
|
146 | edit it and have the file be executed automatically. | |||
|
147 | ||||
|
148 | If the object is a macro (see %macro for details), this opens up your | |||
|
149 | specified editor with a temporary file containing the macro's data. | |||
|
150 | Upon exit, the macro is reloaded with the contents of the file. | |||
|
151 | ||||
|
152 | Note: opening at an exact line is only supported under Unix, and some | |||
|
153 | editors (like kedit and gedit up to Gnome 2.8) do not understand the | |||
|
154 | '+NUMBER' parameter necessary for this feature. Good editors like | |||
|
155 | (X)Emacs, vi, jed, pico and joe all do. | |||
|
156 | ||||
|
157 | - If the argument is not found as a variable, IPython will look for a | |||
|
158 | file with that name (adding .py if necessary) and load it into the | |||
|
159 | editor. It will execute its contents with execfile() when you exit, | |||
|
160 | loading any code in the file into your interactive namespace. | |||
|
161 | ||||
|
162 | After executing your code, %edit will return as output the code you | |||
|
163 | typed in the editor (except when it was an existing file). This way | |||
|
164 | you can reload the code in further invocations of %edit as a variable, | |||
|
165 | via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of | |||
|
166 | the output. | |||
|
167 | ||||
|
168 | Note that %edit is also available through the alias %ed. | |||
|
169 | ||||
|
170 | This is an example of creating a simple function inside the editor and | |||
|
171 | then modifying it. First, start up the editor: | |||
|
172 | ||||
|
173 | In [1]: ed | |||
|
174 | Editing... done. Executing edited code... | |||
|
175 | Out[1]: 'def foo():n print "foo() was defined in an editing session"n' | |||
|
176 | ||||
|
177 | We can then call the function foo(): | |||
|
178 | ||||
|
179 | In [2]: foo() | |||
|
180 | foo() was defined in an editing session | |||
|
181 | ||||
|
182 | Now we edit foo. IPython automatically loads the editor with the | |||
|
183 | (temporary) file where foo() was previously defined: | |||
|
184 | ||||
|
185 | In [3]: ed foo | |||
|
186 | Editing... done. Executing edited code... | |||
|
187 | ||||
|
188 | And if we call foo() again we get the modified version: | |||
|
189 | ||||
|
190 | In [4]: foo() | |||
|
191 | foo() has now been changed! | |||
|
192 | ||||
|
193 | Here is an example of how to edit a code snippet successive | |||
|
194 | times. First we call the editor: | |||
|
195 | ||||
|
196 | In [5]: ed | |||
|
197 | Editing... done. Executing edited code... | |||
|
198 | hello | |||
|
199 | Out[5]: "print 'hello'n" | |||
|
200 | ||||
|
201 | Now we call it again with the previous output (stored in _): | |||
|
202 | ||||
|
203 | In [6]: ed _ | |||
|
204 | Editing... done. Executing edited code... | |||
|
205 | hello world | |||
|
206 | Out[6]: "print 'hello world'n" | |||
|
207 | ||||
|
208 | Now we call it with the output #8 (stored in _8, also as Out[8]): | |||
|
209 | ||||
|
210 | In [7]: ed _8 | |||
|
211 | Editing... done. Executing edited code... | |||
|
212 | hello again | |||
|
213 | Out[7]: "print 'hello again'n" | |||
|
214 | ||||
|
215 | ||||
|
216 | Changing the default editor hook: | |||
|
217 | ||||
|
218 | If you wish to write your own editor hook, you can put it in a | |||
|
219 | configuration file which you load at startup time. The default hook | |||
|
220 | is defined in the IPython.core.hooks module, and you can use that as a | |||
|
221 | starting example for further modifications. That file also has | |||
|
222 | general instructions on how to set a new hook for use once you've | |||
|
223 | defined it.""" | |||
|
224 | ||||
|
225 | # FIXME: This function has become a convoluted mess. It needs a | |||
|
226 | # ground-up rewrite with clean, simple logic. | |||
|
227 | ||||
|
228 | def make_filename(arg): | |||
|
229 | "Make a filename from the given args" | |||
|
230 | try: | |||
|
231 | filename = get_py_filename(arg) | |||
|
232 | except IOError: | |||
|
233 | if args.endswith('.py'): | |||
|
234 | filename = arg | |||
|
235 | else: | |||
|
236 | filename = None | |||
|
237 | return filename | |||
|
238 | ||||
|
239 | # custom exceptions | |||
|
240 | class DataIsObject(Exception): pass | |||
|
241 | ||||
|
242 | opts,args = self.parse_options(parameter_s,'prn:') | |||
|
243 | # Set a few locals from the options for convenience: | |||
|
244 | opts_p = opts.has_key('p') | |||
|
245 | opts_r = opts.has_key('r') | |||
|
246 | ||||
|
247 | # Default line number value | |||
|
248 | lineno = opts.get('n',None) | |||
|
249 | ||||
|
250 | if opts_p: | |||
|
251 | args = '_%s' % last_call[0] | |||
|
252 | if not self.shell.user_ns.has_key(args): | |||
|
253 | args = last_call[1] | |||
|
254 | ||||
|
255 | # use last_call to remember the state of the previous call, but don't | |||
|
256 | # let it be clobbered by successive '-p' calls. | |||
|
257 | try: | |||
|
258 | last_call[0] = self.shell.displayhook.prompt_count | |||
|
259 | if not opts_p: | |||
|
260 | last_call[1] = parameter_s | |||
|
261 | except: | |||
|
262 | pass | |||
|
263 | ||||
|
264 | # by default this is done with temp files, except when the given | |||
|
265 | # arg is a filename | |||
|
266 | use_temp = 1 | |||
|
267 | ||||
|
268 | if re.match(r'\d',args): | |||
|
269 | # Mode where user specifies ranges of lines, like in %macro. | |||
|
270 | # This means that you can't edit files whose names begin with | |||
|
271 | # numbers this way. Tough. | |||
|
272 | ranges = args.split() | |||
|
273 | data = ''.join(self.extract_input_slices(ranges,opts_r)) | |||
|
274 | elif args.endswith('.py'): | |||
|
275 | filename = make_filename(args) | |||
|
276 | data = '' | |||
|
277 | use_temp = 0 | |||
|
278 | elif args: | |||
|
279 | try: | |||
|
280 | # Load the parameter given as a variable. If not a string, | |||
|
281 | # process it as an object instead (below) | |||
|
282 | ||||
|
283 | #print '*** args',args,'type',type(args) # dbg | |||
|
284 | data = eval(args,self.shell.user_ns) | |||
|
285 | if not type(data) in StringTypes: | |||
|
286 | raise DataIsObject | |||
|
287 | ||||
|
288 | except (NameError,SyntaxError): | |||
|
289 | # given argument is not a variable, try as a filename | |||
|
290 | filename = make_filename(args) | |||
|
291 | if filename is None: | |||
|
292 | warn("Argument given (%s) can't be found as a variable " | |||
|
293 | "or as a filename." % args) | |||
|
294 | return | |||
|
295 | ||||
|
296 | data = '' | |||
|
297 | use_temp = 0 | |||
|
298 | except DataIsObject: | |||
|
299 | ||||
|
300 | # macros have a special edit function | |||
|
301 | if isinstance(data,Macro): | |||
|
302 | self._edit_macro(args,data) | |||
|
303 | return | |||
|
304 | ||||
|
305 | # For objects, try to edit the file where they are defined | |||
|
306 | try: | |||
|
307 | filename = inspect.getabsfile(data) | |||
|
308 | if 'fakemodule' in filename.lower() and inspect.isclass(data): | |||
|
309 | # class created by %edit? Try to find source | |||
|
310 | # by looking for method definitions instead, the | |||
|
311 | # __module__ in those classes is FakeModule. | |||
|
312 | attrs = [getattr(data, aname) for aname in dir(data)] | |||
|
313 | for attr in attrs: | |||
|
314 | if not inspect.ismethod(attr): | |||
|
315 | continue | |||
|
316 | filename = inspect.getabsfile(attr) | |||
|
317 | if filename and 'fakemodule' not in filename.lower(): | |||
|
318 | # change the attribute to be the edit target instead | |||
|
319 | data = attr | |||
|
320 | break | |||
|
321 | ||||
|
322 | datafile = 1 | |||
|
323 | except TypeError: | |||
|
324 | filename = make_filename(args) | |||
|
325 | datafile = 1 | |||
|
326 | warn('Could not find file where `%s` is defined.\n' | |||
|
327 | 'Opening a file named `%s`' % (args,filename)) | |||
|
328 | # Now, make sure we can actually read the source (if it was in | |||
|
329 | # a temp file it's gone by now). | |||
|
330 | if datafile: | |||
|
331 | try: | |||
|
332 | if lineno is None: | |||
|
333 | lineno = inspect.getsourcelines(data)[1] | |||
|
334 | except IOError: | |||
|
335 | filename = make_filename(args) | |||
|
336 | if filename is None: | |||
|
337 | warn('The file `%s` where `%s` was defined cannot ' | |||
|
338 | 'be read.' % (filename,data)) | |||
|
339 | return | |||
|
340 | use_temp = 0 | |||
|
341 | else: | |||
|
342 | data = '' | |||
|
343 | ||||
|
344 | if use_temp: | |||
|
345 | filename = self.shell.mktempfile(data) | |||
|
346 | print 'IPython will make a temporary file named:',filename | |||
|
347 | ||||
|
348 | payload = { | |||
|
349 | 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic', | |||
|
350 | 'filename' : filename, | |||
|
351 | 'line_number' : lineno | |||
|
352 | } | |||
|
353 | self.payload_manager.write_payload(payload) | |||
|
354 | ||||
|
355 | ||||
69 | InteractiveShellABC.register(ZMQInteractiveShell) |
|
356 | InteractiveShellABC.register(ZMQInteractiveShell) | |
70 |
|
357 | |||
71 |
|
358 |
General Comments 0
You need to be logged in to leave comments.
Login now