Show More
@@ -66,6 +66,319 b' class ZMQInteractiveShell(InteractiveShell):' | |||||
66 | Term = IPython.utils.io.IOTerm() |
|
66 | Term = IPython.utils.io.IOTerm() | |
67 | IPython.utils.io.Term = Term |
|
67 | IPython.utils.io.Term = Term | |
68 |
|
68 | |||
|
69 | def magic_edit(self,parameter_s='',last_call=['','']): | |||
|
70 | """Bring up an editor and execute the resulting code. | |||
|
71 | ||||
|
72 | Usage: | |||
|
73 | %edit [options] [args] | |||
|
74 | ||||
|
75 | %edit runs IPython's editor hook. The default version of this hook is | |||
|
76 | set to call the __IPYTHON__.rc.editor command. This is read from your | |||
|
77 | environment variable $EDITOR. If this isn't found, it will default to | |||
|
78 | vi under Linux/Unix and to notepad under Windows. See the end of this | |||
|
79 | docstring for how to change the editor hook. | |||
|
80 | ||||
|
81 | You can also set the value of this editor via the command line option | |||
|
82 | '-editor' or in your ipythonrc file. This is useful if you wish to use | |||
|
83 | specifically for IPython an editor different from your typical default | |||
|
84 | (and for Windows users who typically don't set environment variables). | |||
|
85 | ||||
|
86 | This command allows you to conveniently edit multi-line code right in | |||
|
87 | your IPython session. | |||
|
88 | ||||
|
89 | If called without arguments, %edit opens up an empty editor with a | |||
|
90 | temporary file and will execute the contents of this file when you | |||
|
91 | close it (don't forget to save it!). | |||
|
92 | ||||
|
93 | ||||
|
94 | Options: | |||
|
95 | ||||
|
96 | -n <number>: open the editor at a specified line number. By default, | |||
|
97 | the IPython editor hook uses the unix syntax 'editor +N filename', but | |||
|
98 | you can configure this by providing your own modified hook if your | |||
|
99 | favorite editor supports line-number specifications with a different | |||
|
100 | syntax. | |||
|
101 | ||||
|
102 | -p: this will call the editor with the same data as the previous time | |||
|
103 | it was used, regardless of how long ago (in your current session) it | |||
|
104 | was. | |||
|
105 | ||||
|
106 | -r: use 'raw' input. This option only applies to input taken from the | |||
|
107 | user's history. By default, the 'processed' history is used, so that | |||
|
108 | magics are loaded in their transformed version to valid Python. If | |||
|
109 | this option is given, the raw input as typed as the command line is | |||
|
110 | used instead. When you exit the editor, it will be executed by | |||
|
111 | IPython's own processor. | |||
|
112 | ||||
|
113 | -x: do not execute the edited code immediately upon exit. This is | |||
|
114 | mainly useful if you are editing programs which need to be called with | |||
|
115 | command line arguments, which you can then do using %run. | |||
|
116 | ||||
|
117 | ||||
|
118 | Arguments: | |||
|
119 | ||||
|
120 | If arguments are given, the following possibilites exist: | |||
|
121 | ||||
|
122 | - The arguments are numbers or pairs of colon-separated numbers (like | |||
|
123 | 1 4:8 9). These are interpreted as lines of previous input to be | |||
|
124 | loaded into the editor. The syntax is the same of the %macro command. | |||
|
125 | ||||
|
126 | - If the argument doesn't start with a number, it is evaluated as a | |||
|
127 | variable and its contents loaded into the editor. You can thus edit | |||
|
128 | any string which contains python code (including the result of | |||
|
129 | previous edits). | |||
|
130 | ||||
|
131 | - If the argument is the name of an object (other than a string), | |||
|
132 | IPython will try to locate the file where it was defined and open the | |||
|
133 | editor at the point where it is defined. You can use `%edit function` | |||
|
134 | to load an editor exactly at the point where 'function' is defined, | |||
|
135 | edit it and have the file be executed automatically. | |||
|
136 | ||||
|
137 | If the object is a macro (see %macro for details), this opens up your | |||
|
138 | specified editor with a temporary file containing the macro's data. | |||
|
139 | Upon exit, the macro is reloaded with the contents of the file. | |||
|
140 | ||||
|
141 | Note: opening at an exact line is only supported under Unix, and some | |||
|
142 | editors (like kedit and gedit up to Gnome 2.8) do not understand the | |||
|
143 | '+NUMBER' parameter necessary for this feature. Good editors like | |||
|
144 | (X)Emacs, vi, jed, pico and joe all do. | |||
|
145 | ||||
|
146 | - If the argument is not found as a variable, IPython will look for a | |||
|
147 | file with that name (adding .py if necessary) and load it into the | |||
|
148 | editor. It will execute its contents with execfile() when you exit, | |||
|
149 | loading any code in the file into your interactive namespace. | |||
|
150 | ||||
|
151 | After executing your code, %edit will return as output the code you | |||
|
152 | typed in the editor (except when it was an existing file). This way | |||
|
153 | you can reload the code in further invocations of %edit as a variable, | |||
|
154 | via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of | |||
|
155 | the output. | |||
|
156 | ||||
|
157 | Note that %edit is also available through the alias %ed. | |||
|
158 | ||||
|
159 | This is an example of creating a simple function inside the editor and | |||
|
160 | then modifying it. First, start up the editor: | |||
|
161 | ||||
|
162 | In [1]: ed | |||
|
163 | Editing... done. Executing edited code... | |||
|
164 | Out[1]: 'def foo():n print "foo() was defined in an editing session"n' | |||
|
165 | ||||
|
166 | We can then call the function foo(): | |||
|
167 | ||||
|
168 | In [2]: foo() | |||
|
169 | foo() was defined in an editing session | |||
|
170 | ||||
|
171 | Now we edit foo. IPython automatically loads the editor with the | |||
|
172 | (temporary) file where foo() was previously defined: | |||
|
173 | ||||
|
174 | In [3]: ed foo | |||
|
175 | Editing... done. Executing edited code... | |||
|
176 | ||||
|
177 | And if we call foo() again we get the modified version: | |||
|
178 | ||||
|
179 | In [4]: foo() | |||
|
180 | foo() has now been changed! | |||
|
181 | ||||
|
182 | Here is an example of how to edit a code snippet successive | |||
|
183 | times. First we call the editor: | |||
|
184 | ||||
|
185 | In [5]: ed | |||
|
186 | Editing... done. Executing edited code... | |||
|
187 | hello | |||
|
188 | Out[5]: "print 'hello'n" | |||
|
189 | ||||
|
190 | Now we call it again with the previous output (stored in _): | |||
|
191 | ||||
|
192 | In [6]: ed _ | |||
|
193 | Editing... done. Executing edited code... | |||
|
194 | hello world | |||
|
195 | Out[6]: "print 'hello world'n" | |||
|
196 | ||||
|
197 | Now we call it with the output #8 (stored in _8, also as Out[8]): | |||
|
198 | ||||
|
199 | In [7]: ed _8 | |||
|
200 | Editing... done. Executing edited code... | |||
|
201 | hello again | |||
|
202 | Out[7]: "print 'hello again'n" | |||
|
203 | ||||
|
204 | ||||
|
205 | Changing the default editor hook: | |||
|
206 | ||||
|
207 | If you wish to write your own editor hook, you can put it in a | |||
|
208 | configuration file which you load at startup time. The default hook | |||
|
209 | is defined in the IPython.core.hooks module, and you can use that as a | |||
|
210 | starting example for further modifications. That file also has | |||
|
211 | general instructions on how to set a new hook for use once you've | |||
|
212 | defined it.""" | |||
|
213 | ||||
|
214 | # FIXME: This function has become a convoluted mess. It needs a | |||
|
215 | # ground-up rewrite with clean, simple logic. | |||
|
216 | ||||
|
217 | def make_filename(arg): | |||
|
218 | "Make a filename from the given args" | |||
|
219 | try: | |||
|
220 | filename = get_py_filename(arg) | |||
|
221 | except IOError: | |||
|
222 | if args.endswith('.py'): | |||
|
223 | filename = arg | |||
|
224 | else: | |||
|
225 | filename = None | |||
|
226 | return filename | |||
|
227 | ||||
|
228 | # custom exceptions | |||
|
229 | class DataIsObject(Exception): pass | |||
|
230 | ||||
|
231 | opts,args = self.parse_options(parameter_s,'prn:') | |||
|
232 | # Set a few locals from the options for convenience: | |||
|
233 | opts_p = opts.has_key('p') | |||
|
234 | opts_r = opts.has_key('r') | |||
|
235 | ||||
|
236 | # Default line number value | |||
|
237 | lineno = opts.get('n',None) | |||
|
238 | ||||
|
239 | if opts_p: | |||
|
240 | args = '_%s' % last_call[0] | |||
|
241 | if not self.shell.user_ns.has_key(args): | |||
|
242 | args = last_call[1] | |||
|
243 | ||||
|
244 | # use last_call to remember the state of the previous call, but don't | |||
|
245 | # let it be clobbered by successive '-p' calls. | |||
|
246 | try: | |||
|
247 | last_call[0] = self.shell.displayhook.prompt_count | |||
|
248 | if not opts_p: | |||
|
249 | last_call[1] = parameter_s | |||
|
250 | except: | |||
|
251 | pass | |||
|
252 | ||||
|
253 | # by default this is done with temp files, except when the given | |||
|
254 | # arg is a filename | |||
|
255 | use_temp = 1 | |||
|
256 | ||||
|
257 | if re.match(r'\d',args): | |||
|
258 | # Mode where user specifies ranges of lines, like in %macro. | |||
|
259 | # This means that you can't edit files whose names begin with | |||
|
260 | # numbers this way. Tough. | |||
|
261 | ranges = args.split() | |||
|
262 | data = ''.join(self.extract_input_slices(ranges,opts_r)) | |||
|
263 | elif args.endswith('.py'): | |||
|
264 | filename = make_filename(args) | |||
|
265 | data = '' | |||
|
266 | use_temp = 0 | |||
|
267 | elif args: | |||
|
268 | try: | |||
|
269 | # Load the parameter given as a variable. If not a string, | |||
|
270 | # process it as an object instead (below) | |||
|
271 | ||||
|
272 | #print '*** args',args,'type',type(args) # dbg | |||
|
273 | data = eval(args,self.shell.user_ns) | |||
|
274 | if not type(data) in StringTypes: | |||
|
275 | raise DataIsObject | |||
|
276 | ||||
|
277 | except (NameError,SyntaxError): | |||
|
278 | # given argument is not a variable, try as a filename | |||
|
279 | filename = make_filename(args) | |||
|
280 | if filename is None: | |||
|
281 | warn("Argument given (%s) can't be found as a variable " | |||
|
282 | "or as a filename." % args) | |||
|
283 | return | |||
|
284 | ||||
|
285 | data = '' | |||
|
286 | use_temp = 0 | |||
|
287 | except DataIsObject: | |||
|
288 | ||||
|
289 | # macros have a special edit function | |||
|
290 | if isinstance(data,Macro): | |||
|
291 | self._edit_macro(args,data) | |||
|
292 | return | |||
|
293 | ||||
|
294 | # For objects, try to edit the file where they are defined | |||
|
295 | try: | |||
|
296 | filename = inspect.getabsfile(data) | |||
|
297 | if 'fakemodule' in filename.lower() and inspect.isclass(data): | |||
|
298 | # class created by %edit? Try to find source | |||
|
299 | # by looking for method definitions instead, the | |||
|
300 | # __module__ in those classes is FakeModule. | |||
|
301 | attrs = [getattr(data, aname) for aname in dir(data)] | |||
|
302 | for attr in attrs: | |||
|
303 | if not inspect.ismethod(attr): | |||
|
304 | continue | |||
|
305 | filename = inspect.getabsfile(attr) | |||
|
306 | if filename and 'fakemodule' not in filename.lower(): | |||
|
307 | # change the attribute to be the edit target instead | |||
|
308 | data = attr | |||
|
309 | break | |||
|
310 | ||||
|
311 | datafile = 1 | |||
|
312 | except TypeError: | |||
|
313 | filename = make_filename(args) | |||
|
314 | datafile = 1 | |||
|
315 | warn('Could not find file where `%s` is defined.\n' | |||
|
316 | 'Opening a file named `%s`' % (args,filename)) | |||
|
317 | # Now, make sure we can actually read the source (if it was in | |||
|
318 | # a temp file it's gone by now). | |||
|
319 | if datafile: | |||
|
320 | try: | |||
|
321 | if lineno is None: | |||
|
322 | lineno = inspect.getsourcelines(data)[1] | |||
|
323 | except IOError: | |||
|
324 | filename = make_filename(args) | |||
|
325 | if filename is None: | |||
|
326 | warn('The file `%s` where `%s` was defined cannot ' | |||
|
327 | 'be read.' % (filename,data)) | |||
|
328 | return | |||
|
329 | use_temp = 0 | |||
|
330 | else: | |||
|
331 | data = '' | |||
|
332 | ||||
|
333 | if use_temp: | |||
|
334 | filename = self.shell.mktempfile(data) | |||
|
335 | print 'IPython will make a temporary file named:',filename | |||
|
336 | ||||
|
337 | payload = { | |||
|
338 | 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic', | |||
|
339 | 'filename' : filename, | |||
|
340 | 'line_number' : lineno | |||
|
341 | } | |||
|
342 | self.payload_manager.write_payload(payload) | |||
|
343 | ||||
|
344 | # # do actual editing here | |||
|
345 | # print 'Editing...', | |||
|
346 | # sys.stdout.flush() | |||
|
347 | # try: | |||
|
348 | # # Quote filenames that may have spaces in them | |||
|
349 | # if ' ' in filename: | |||
|
350 | # filename = "%s" % filename | |||
|
351 | # self.shell.hooks.editor(filename,lineno) | |||
|
352 | # except TryNext: | |||
|
353 | # warn('Could not open editor') | |||
|
354 | # return | |||
|
355 | # | |||
|
356 | # # XXX TODO: should this be generalized for all string vars? | |||
|
357 | # # For now, this is special-cased to blocks created by cpaste | |||
|
358 | # if args.strip() == 'pasted_block': | |||
|
359 | # self.shell.user_ns['pasted_block'] = file_read(filename) | |||
|
360 | # | |||
|
361 | # if opts.has_key('x'): # -x prevents actual execution | |||
|
362 | ||||
|
363 | # else: | |||
|
364 | # print 'done. Executing edited code...' | |||
|
365 | # if opts_r: | |||
|
366 | # self.shell.runlines(file_read(filename)) | |||
|
367 | # else: | |||
|
368 | # self.shell.safe_execfile(filename,self.shell.user_ns, | |||
|
369 | # self.shell.user_ns) | |||
|
370 | # | |||
|
371 | # | |||
|
372 | # if use_temp: | |||
|
373 | # try: | |||
|
374 | # return open(filename).read() | |||
|
375 | # except IOError,msg: | |||
|
376 | # if msg.filename == filename: | |||
|
377 | # warn('File not found. Did you forget to save?') | |||
|
378 | # return | |||
|
379 | # else: | |||
|
380 | # self.shell.showtraceback() | |||
|
381 | ||||
69 | InteractiveShellABC.register(ZMQInteractiveShell) |
|
382 | InteractiveShellABC.register(ZMQInteractiveShell) | |
70 |
|
383 | |||
71 |
|
384 |
General Comments 0
You need to be logged in to leave comments.
Login now