##// END OF EJS Templates
Use oinspect in CodeMagics._find_edit_target...
Takafumi Arakaki -
Show More
@@ -1,513 +1,513 b''
1 """Implementation of code management magic functions.
1 """Implementation of code management magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import inspect
16 import inspect
17 import io
17 import io
18 import json
18 import json
19 import os
19 import os
20 import sys
20 import sys
21 from urllib2 import urlopen
21 from urllib2 import urlopen
22
22
23 # Our own packages
23 # Our own packages
24 from IPython.core.error import TryNext
24 from IPython.core.error import TryNext
25 from IPython.core.macro import Macro
25 from IPython.core.macro import Macro
26 from IPython.core.magic import Magics, magics_class, line_magic
26 from IPython.core.magic import Magics, magics_class, line_magic
27 from IPython.core.oinspect import find_file, find_source_lines
27 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.utils import openpy
29 from IPython.utils import openpy
29 from IPython.utils import py3compat
30 from IPython.utils import py3compat
30 from IPython.utils.io import file_read
31 from IPython.utils.io import file_read
31 from IPython.utils.path import get_py_filename, unquote_filename
32 from IPython.utils.path import get_py_filename, unquote_filename
32 from IPython.utils.warn import warn
33 from IPython.utils.warn import warn
33
34
34 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
35 # Magic implementation classes
36 # Magic implementation classes
36 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
37
38
38 # Used for exception handling in magic_edit
39 # Used for exception handling in magic_edit
39 class MacroToEdit(ValueError): pass
40 class MacroToEdit(ValueError): pass
40
41
41
42
42 @magics_class
43 @magics_class
43 class CodeMagics(Magics):
44 class CodeMagics(Magics):
44 """Magics related to code management (loading, saving, editing, ...)."""
45 """Magics related to code management (loading, saving, editing, ...)."""
45
46
46 @line_magic
47 @line_magic
47 def save(self, parameter_s=''):
48 def save(self, parameter_s=''):
48 """Save a set of lines or a macro to a given filename.
49 """Save a set of lines or a macro to a given filename.
49
50
50 Usage:\\
51 Usage:\\
51 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
52 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
52
53
53 Options:
54 Options:
54
55
55 -r: use 'raw' input. By default, the 'processed' history is used,
56 -r: use 'raw' input. By default, the 'processed' history is used,
56 so that magics are loaded in their transformed version to valid
57 so that magics are loaded in their transformed version to valid
57 Python. If this option is given, the raw input as typed as the
58 Python. If this option is given, the raw input as typed as the
58 command line is used instead.
59 command line is used instead.
59
60
60 This function uses the same syntax as %history for input ranges,
61 This function uses the same syntax as %history for input ranges,
61 then saves the lines to the filename you specify.
62 then saves the lines to the filename you specify.
62
63
63 It adds a '.py' extension to the file if you don't do so yourself, and
64 It adds a '.py' extension to the file if you don't do so yourself, and
64 it asks for confirmation before overwriting existing files.
65 it asks for confirmation before overwriting existing files.
65
66
66 If `-r` option is used, the default extension is `.ipy`.
67 If `-r` option is used, the default extension is `.ipy`.
67 """
68 """
68
69
69 opts,args = self.parse_options(parameter_s,'r',mode='list')
70 opts,args = self.parse_options(parameter_s,'r',mode='list')
70 raw = 'r' in opts
71 raw = 'r' in opts
71 ext = u'.ipy' if raw else u'.py'
72 ext = u'.ipy' if raw else u'.py'
72 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
73 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
73 if not fname.endswith((u'.py',u'.ipy')):
74 if not fname.endswith((u'.py',u'.ipy')):
74 fname += ext
75 fname += ext
75 if os.path.isfile(fname):
76 if os.path.isfile(fname):
76 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
77 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
77 if not overwrite :
78 if not overwrite :
78 print 'Operation cancelled.'
79 print 'Operation cancelled.'
79 return
80 return
80 try:
81 try:
81 cmds = self.shell.find_user_code(codefrom,raw)
82 cmds = self.shell.find_user_code(codefrom,raw)
82 except (TypeError, ValueError) as e:
83 except (TypeError, ValueError) as e:
83 print e.args[0]
84 print e.args[0]
84 return
85 return
85 with io.open(fname,'w', encoding="utf-8") as f:
86 with io.open(fname,'w', encoding="utf-8") as f:
86 f.write(u"# coding: utf-8\n")
87 f.write(u"# coding: utf-8\n")
87 f.write(py3compat.cast_unicode(cmds))
88 f.write(py3compat.cast_unicode(cmds))
88 print 'The following commands were written to file `%s`:' % fname
89 print 'The following commands were written to file `%s`:' % fname
89 print cmds
90 print cmds
90
91
91 @line_magic
92 @line_magic
92 def pastebin(self, parameter_s=''):
93 def pastebin(self, parameter_s=''):
93 """Upload code to Github's Gist paste bin, returning the URL.
94 """Upload code to Github's Gist paste bin, returning the URL.
94
95
95 Usage:\\
96 Usage:\\
96 %pastebin [-d "Custom description"] 1-7
97 %pastebin [-d "Custom description"] 1-7
97
98
98 The argument can be an input history range, a filename, or the name of a
99 The argument can be an input history range, a filename, or the name of a
99 string or macro.
100 string or macro.
100
101
101 Options:
102 Options:
102
103
103 -d: Pass a custom description for the gist. The default will say
104 -d: Pass a custom description for the gist. The default will say
104 "Pasted from IPython".
105 "Pasted from IPython".
105 """
106 """
106 opts, args = self.parse_options(parameter_s, 'd:')
107 opts, args = self.parse_options(parameter_s, 'd:')
107
108
108 try:
109 try:
109 code = self.shell.find_user_code(args)
110 code = self.shell.find_user_code(args)
110 except (ValueError, TypeError) as e:
111 except (ValueError, TypeError) as e:
111 print e.args[0]
112 print e.args[0]
112 return
113 return
113
114
114 post_data = json.dumps({
115 post_data = json.dumps({
115 "description": opts.get('d', "Pasted from IPython"),
116 "description": opts.get('d', "Pasted from IPython"),
116 "public": True,
117 "public": True,
117 "files": {
118 "files": {
118 "file1.py": {
119 "file1.py": {
119 "content": code
120 "content": code
120 }
121 }
121 }
122 }
122 }).encode('utf-8')
123 }).encode('utf-8')
123
124
124 response = urlopen("https://api.github.com/gists", post_data)
125 response = urlopen("https://api.github.com/gists", post_data)
125 response_data = json.loads(response.read().decode('utf-8'))
126 response_data = json.loads(response.read().decode('utf-8'))
126 return response_data['html_url']
127 return response_data['html_url']
127
128
128 @line_magic
129 @line_magic
129 def loadpy(self, arg_s):
130 def loadpy(self, arg_s):
130 """Alias of `%load`
131 """Alias of `%load`
131
132
132 `%loadpy` has gained some flexibility and droped the requirement of a `.py`
133 `%loadpy` has gained some flexibility and droped the requirement of a `.py`
133 extension. So it has been renamed simply into %load. You can look at
134 extension. So it has been renamed simply into %load. You can look at
134 `%load`'s docstring for more info.
135 `%load`'s docstring for more info.
135 """
136 """
136 self.load(arg_s)
137 self.load(arg_s)
137
138
138 @line_magic
139 @line_magic
139 def load(self, arg_s):
140 def load(self, arg_s):
140 """Load code into the current frontend.
141 """Load code into the current frontend.
141
142
142 Usage:\\
143 Usage:\\
143 %load [options] source
144 %load [options] source
144
145
145 where source can be a filename, URL, input history range or macro
146 where source can be a filename, URL, input history range or macro
146
147
147 Options:
148 Options:
148 --------
149 --------
149 -y : Don't ask confirmation for loading source above 200 000 characters.
150 -y : Don't ask confirmation for loading source above 200 000 characters.
150
151
151 This magic command can either take a local filename, a URL, an history
152 This magic command can either take a local filename, a URL, an history
152 range (see %history) or a macro as argument, it will prompt for
153 range (see %history) or a macro as argument, it will prompt for
153 confirmation before loading source with more than 200 000 characters, unless
154 confirmation before loading source with more than 200 000 characters, unless
154 -y flag is passed or if the frontend does not support raw_input::
155 -y flag is passed or if the frontend does not support raw_input::
155
156
156 %load myscript.py
157 %load myscript.py
157 %load 7-27
158 %load 7-27
158 %load myMacro
159 %load myMacro
159 %load http://www.example.com/myscript.py
160 %load http://www.example.com/myscript.py
160 """
161 """
161 opts,args = self.parse_options(arg_s,'y')
162 opts,args = self.parse_options(arg_s,'y')
162
163
163 contents = self.shell.find_user_code(args)
164 contents = self.shell.find_user_code(args)
164 l = len(contents)
165 l = len(contents)
165
166
166 # 200 000 is ~ 2500 full 80 caracter lines
167 # 200 000 is ~ 2500 full 80 caracter lines
167 # so in average, more than 5000 lines
168 # so in average, more than 5000 lines
168 if l > 200000 and 'y' not in opts:
169 if l > 200000 and 'y' not in opts:
169 try:
170 try:
170 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
171 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
171 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
172 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
172 except StdinNotImplementedError:
173 except StdinNotImplementedError:
173 #asume yes if raw input not implemented
174 #asume yes if raw input not implemented
174 ans = True
175 ans = True
175
176
176 if ans is False :
177 if ans is False :
177 print 'Operation cancelled.'
178 print 'Operation cancelled.'
178 return
179 return
179
180
180 self.shell.set_next_input(contents)
181 self.shell.set_next_input(contents)
181
182
182 @staticmethod
183 @staticmethod
183 def _find_edit_target(shell, args, opts, last_call):
184 def _find_edit_target(shell, args, opts, last_call):
184 """Utility method used by magic_edit to find what to edit."""
185 """Utility method used by magic_edit to find what to edit."""
185
186
186 def make_filename(arg):
187 def make_filename(arg):
187 "Make a filename from the given args"
188 "Make a filename from the given args"
188 arg = unquote_filename(arg)
189 arg = unquote_filename(arg)
189 try:
190 try:
190 filename = get_py_filename(arg)
191 filename = get_py_filename(arg)
191 except IOError:
192 except IOError:
192 # If it ends with .py but doesn't already exist, assume we want
193 # If it ends with .py but doesn't already exist, assume we want
193 # a new file.
194 # a new file.
194 if arg.endswith('.py'):
195 if arg.endswith('.py'):
195 filename = arg
196 filename = arg
196 else:
197 else:
197 filename = None
198 filename = None
198 return filename
199 return filename
199
200
200 # Set a few locals from the options for convenience:
201 # Set a few locals from the options for convenience:
201 opts_prev = 'p' in opts
202 opts_prev = 'p' in opts
202 opts_raw = 'r' in opts
203 opts_raw = 'r' in opts
203
204
204 # custom exceptions
205 # custom exceptions
205 class DataIsObject(Exception): pass
206 class DataIsObject(Exception): pass
206
207
207 # Default line number value
208 # Default line number value
208 lineno = opts.get('n',None)
209 lineno = opts.get('n',None)
209
210
210 if opts_prev:
211 if opts_prev:
211 args = '_%s' % last_call[0]
212 args = '_%s' % last_call[0]
212 if not shell.user_ns.has_key(args):
213 if not shell.user_ns.has_key(args):
213 args = last_call[1]
214 args = last_call[1]
214
215
215 # use last_call to remember the state of the previous call, but don't
216 # use last_call to remember the state of the previous call, but don't
216 # let it be clobbered by successive '-p' calls.
217 # let it be clobbered by successive '-p' calls.
217 try:
218 try:
218 last_call[0] = shell.displayhook.prompt_count
219 last_call[0] = shell.displayhook.prompt_count
219 if not opts_prev:
220 if not opts_prev:
220 last_call[1] = args
221 last_call[1] = args
221 except:
222 except:
222 pass
223 pass
223
224
224 # by default this is done with temp files, except when the given
225 # by default this is done with temp files, except when the given
225 # arg is a filename
226 # arg is a filename
226 use_temp = True
227 use_temp = True
227
228
228 data = ''
229 data = ''
229
230
230 # First, see if the arguments should be a filename.
231 # First, see if the arguments should be a filename.
231 filename = make_filename(args)
232 filename = make_filename(args)
232 if filename:
233 if filename:
233 use_temp = False
234 use_temp = False
234 elif args:
235 elif args:
235 # Mode where user specifies ranges of lines, like in %macro.
236 # Mode where user specifies ranges of lines, like in %macro.
236 data = shell.extract_input_lines(args, opts_raw)
237 data = shell.extract_input_lines(args, opts_raw)
237 if not data:
238 if not data:
238 try:
239 try:
239 # Load the parameter given as a variable. If not a string,
240 # Load the parameter given as a variable. If not a string,
240 # process it as an object instead (below)
241 # process it as an object instead (below)
241
242
242 #print '*** args',args,'type',type(args) # dbg
243 #print '*** args',args,'type',type(args) # dbg
243 data = eval(args, shell.user_ns)
244 data = eval(args, shell.user_ns)
244 if not isinstance(data, basestring):
245 if not isinstance(data, basestring):
245 raise DataIsObject
246 raise DataIsObject
246
247
247 except (NameError,SyntaxError):
248 except (NameError,SyntaxError):
248 # given argument is not a variable, try as a filename
249 # given argument is not a variable, try as a filename
249 filename = make_filename(args)
250 filename = make_filename(args)
250 if filename is None:
251 if filename is None:
251 warn("Argument given (%s) can't be found as a variable "
252 warn("Argument given (%s) can't be found as a variable "
252 "or as a filename." % args)
253 "or as a filename." % args)
253 return
254 return
254 use_temp = False
255 use_temp = False
255
256
256 except DataIsObject:
257 except DataIsObject:
257 # macros have a special edit function
258 # macros have a special edit function
258 if isinstance(data, Macro):
259 if isinstance(data, Macro):
259 raise MacroToEdit(data)
260 raise MacroToEdit(data)
260
261
261 # For objects, try to edit the file where they are defined
262 # For objects, try to edit the file where they are defined
262 try:
263 filename = find_file(data)
263 filename = inspect.getabsfile(data)
264 if filename:
264 if 'fakemodule' in filename.lower() and \
265 if 'fakemodule' in filename.lower() and \
265 inspect.isclass(data):
266 inspect.isclass(data):
266 # class created by %edit? Try to find source
267 # class created by %edit? Try to find source
267 # by looking for method definitions instead, the
268 # by looking for method definitions instead, the
268 # __module__ in those classes is FakeModule.
269 # __module__ in those classes is FakeModule.
269 attrs = [getattr(data, aname) for aname in dir(data)]
270 attrs = [getattr(data, aname) for aname in dir(data)]
270 for attr in attrs:
271 for attr in attrs:
271 if not inspect.ismethod(attr):
272 if not inspect.ismethod(attr):
272 continue
273 continue
273 filename = inspect.getabsfile(attr)
274 filename = find_file(attr)
274 if filename and \
275 if filename and \
275 'fakemodule' not in filename.lower():
276 'fakemodule' not in filename.lower():
276 # change the attribute to be the edit
277 # change the attribute to be the edit
277 # target instead
278 # target instead
278 data = attr
279 data = attr
279 break
280 break
280
281
281 datafile = 1
282 datafile = 1
282 except TypeError:
283 if filename is None:
283 filename = make_filename(args)
284 filename = make_filename(args)
284 datafile = 1
285 datafile = 1
285 warn('Could not find file where `%s` is defined.\n'
286 warn('Could not find file where `%s` is defined.\n'
286 'Opening a file named `%s`' % (args, filename))
287 'Opening a file named `%s`' % (args, filename))
287 # Now, make sure we can actually read the source (if it was
288 # Now, make sure we can actually read the source (if it was
288 # in a temp file it's gone by now).
289 # in a temp file it's gone by now).
289 if datafile:
290 if datafile:
290 try:
291 if lineno is None:
291 if lineno is None:
292 lineno = find_source_lines(data)
292 lineno = inspect.getsourcelines(data)[1]
293 if lineno is None:
293 except IOError:
294 filename = make_filename(args)
294 filename = make_filename(args)
295 if filename is None:
295 if filename is None:
296 warn('The file `%s` where `%s` was defined '
296 warn('The file `%s` where `%s` was defined '
297 'cannot be read.' % (filename, data))
297 'cannot be read.' % (filename, data))
298 return
298 return
299 use_temp = False
299 use_temp = False
300
300
301 if use_temp:
301 if use_temp:
302 filename = shell.mktempfile(data)
302 filename = shell.mktempfile(data)
303 print 'IPython will make a temporary file named:',filename
303 print 'IPython will make a temporary file named:',filename
304
304
305 return filename, lineno, use_temp
305 return filename, lineno, use_temp
306
306
307 def _edit_macro(self,mname,macro):
307 def _edit_macro(self,mname,macro):
308 """open an editor with the macro data in a file"""
308 """open an editor with the macro data in a file"""
309 filename = self.shell.mktempfile(macro.value)
309 filename = self.shell.mktempfile(macro.value)
310 self.shell.hooks.editor(filename)
310 self.shell.hooks.editor(filename)
311
311
312 # and make a new macro object, to replace the old one
312 # and make a new macro object, to replace the old one
313 mfile = open(filename)
313 mfile = open(filename)
314 mvalue = mfile.read()
314 mvalue = mfile.read()
315 mfile.close()
315 mfile.close()
316 self.shell.user_ns[mname] = Macro(mvalue)
316 self.shell.user_ns[mname] = Macro(mvalue)
317
317
318 @line_magic
318 @line_magic
319 def ed(self, parameter_s=''):
319 def ed(self, parameter_s=''):
320 """Alias to %edit."""
320 """Alias to %edit."""
321 return self.edit(parameter_s)
321 return self.edit(parameter_s)
322
322
323 @skip_doctest
323 @skip_doctest
324 @line_magic
324 @line_magic
325 def edit(self, parameter_s='',last_call=['','']):
325 def edit(self, parameter_s='',last_call=['','']):
326 """Bring up an editor and execute the resulting code.
326 """Bring up an editor and execute the resulting code.
327
327
328 Usage:
328 Usage:
329 %edit [options] [args]
329 %edit [options] [args]
330
330
331 %edit runs IPython's editor hook. The default version of this hook is
331 %edit runs IPython's editor hook. The default version of this hook is
332 set to call the editor specified by your $EDITOR environment variable.
332 set to call the editor specified by your $EDITOR environment variable.
333 If this isn't found, it will default to vi under Linux/Unix and to
333 If this isn't found, it will default to vi under Linux/Unix and to
334 notepad under Windows. See the end of this docstring for how to change
334 notepad under Windows. See the end of this docstring for how to change
335 the editor hook.
335 the editor hook.
336
336
337 You can also set the value of this editor via the
337 You can also set the value of this editor via the
338 ``TerminalInteractiveShell.editor`` option in your configuration file.
338 ``TerminalInteractiveShell.editor`` option in your configuration file.
339 This is useful if you wish to use a different editor from your typical
339 This is useful if you wish to use a different editor from your typical
340 default with IPython (and for Windows users who typically don't set
340 default with IPython (and for Windows users who typically don't set
341 environment variables).
341 environment variables).
342
342
343 This command allows you to conveniently edit multi-line code right in
343 This command allows you to conveniently edit multi-line code right in
344 your IPython session.
344 your IPython session.
345
345
346 If called without arguments, %edit opens up an empty editor with a
346 If called without arguments, %edit opens up an empty editor with a
347 temporary file and will execute the contents of this file when you
347 temporary file and will execute the contents of this file when you
348 close it (don't forget to save it!).
348 close it (don't forget to save it!).
349
349
350
350
351 Options:
351 Options:
352
352
353 -n <number>: open the editor at a specified line number. By default,
353 -n <number>: open the editor at a specified line number. By default,
354 the IPython editor hook uses the unix syntax 'editor +N filename', but
354 the IPython editor hook uses the unix syntax 'editor +N filename', but
355 you can configure this by providing your own modified hook if your
355 you can configure this by providing your own modified hook if your
356 favorite editor supports line-number specifications with a different
356 favorite editor supports line-number specifications with a different
357 syntax.
357 syntax.
358
358
359 -p: this will call the editor with the same data as the previous time
359 -p: this will call the editor with the same data as the previous time
360 it was used, regardless of how long ago (in your current session) it
360 it was used, regardless of how long ago (in your current session) it
361 was.
361 was.
362
362
363 -r: use 'raw' input. This option only applies to input taken from the
363 -r: use 'raw' input. This option only applies to input taken from the
364 user's history. By default, the 'processed' history is used, so that
364 user's history. By default, the 'processed' history is used, so that
365 magics are loaded in their transformed version to valid Python. If
365 magics are loaded in their transformed version to valid Python. If
366 this option is given, the raw input as typed as the command line is
366 this option is given, the raw input as typed as the command line is
367 used instead. When you exit the editor, it will be executed by
367 used instead. When you exit the editor, it will be executed by
368 IPython's own processor.
368 IPython's own processor.
369
369
370 -x: do not execute the edited code immediately upon exit. This is
370 -x: do not execute the edited code immediately upon exit. This is
371 mainly useful if you are editing programs which need to be called with
371 mainly useful if you are editing programs which need to be called with
372 command line arguments, which you can then do using %run.
372 command line arguments, which you can then do using %run.
373
373
374
374
375 Arguments:
375 Arguments:
376
376
377 If arguments are given, the following possibilities exist:
377 If arguments are given, the following possibilities exist:
378
378
379 - If the argument is a filename, IPython will load that into the
379 - If the argument is a filename, IPython will load that into the
380 editor. It will execute its contents with execfile() when you exit,
380 editor. It will execute its contents with execfile() when you exit,
381 loading any code in the file into your interactive namespace.
381 loading any code in the file into your interactive namespace.
382
382
383 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
383 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
384 The syntax is the same as in the %history magic.
384 The syntax is the same as in the %history magic.
385
385
386 - If the argument is a string variable, its contents are loaded
386 - If the argument is a string variable, its contents are loaded
387 into the editor. You can thus edit any string which contains
387 into the editor. You can thus edit any string which contains
388 python code (including the result of previous edits).
388 python code (including the result of previous edits).
389
389
390 - If the argument is the name of an object (other than a string),
390 - If the argument is the name of an object (other than a string),
391 IPython will try to locate the file where it was defined and open the
391 IPython will try to locate the file where it was defined and open the
392 editor at the point where it is defined. You can use `%edit function`
392 editor at the point where it is defined. You can use `%edit function`
393 to load an editor exactly at the point where 'function' is defined,
393 to load an editor exactly at the point where 'function' is defined,
394 edit it and have the file be executed automatically.
394 edit it and have the file be executed automatically.
395
395
396 - If the object is a macro (see %macro for details), this opens up your
396 - If the object is a macro (see %macro for details), this opens up your
397 specified editor with a temporary file containing the macro's data.
397 specified editor with a temporary file containing the macro's data.
398 Upon exit, the macro is reloaded with the contents of the file.
398 Upon exit, the macro is reloaded with the contents of the file.
399
399
400 Note: opening at an exact line is only supported under Unix, and some
400 Note: opening at an exact line is only supported under Unix, and some
401 editors (like kedit and gedit up to Gnome 2.8) do not understand the
401 editors (like kedit and gedit up to Gnome 2.8) do not understand the
402 '+NUMBER' parameter necessary for this feature. Good editors like
402 '+NUMBER' parameter necessary for this feature. Good editors like
403 (X)Emacs, vi, jed, pico and joe all do.
403 (X)Emacs, vi, jed, pico and joe all do.
404
404
405 After executing your code, %edit will return as output the code you
405 After executing your code, %edit will return as output the code you
406 typed in the editor (except when it was an existing file). This way
406 typed in the editor (except when it was an existing file). This way
407 you can reload the code in further invocations of %edit as a variable,
407 you can reload the code in further invocations of %edit as a variable,
408 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
408 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
409 the output.
409 the output.
410
410
411 Note that %edit is also available through the alias %ed.
411 Note that %edit is also available through the alias %ed.
412
412
413 This is an example of creating a simple function inside the editor and
413 This is an example of creating a simple function inside the editor and
414 then modifying it. First, start up the editor::
414 then modifying it. First, start up the editor::
415
415
416 In [1]: ed
416 In [1]: ed
417 Editing... done. Executing edited code...
417 Editing... done. Executing edited code...
418 Out[1]: 'def foo():\\n print "foo() was defined in an editing
418 Out[1]: 'def foo():\\n print "foo() was defined in an editing
419 session"\\n'
419 session"\\n'
420
420
421 We can then call the function foo()::
421 We can then call the function foo()::
422
422
423 In [2]: foo()
423 In [2]: foo()
424 foo() was defined in an editing session
424 foo() was defined in an editing session
425
425
426 Now we edit foo. IPython automatically loads the editor with the
426 Now we edit foo. IPython automatically loads the editor with the
427 (temporary) file where foo() was previously defined::
427 (temporary) file where foo() was previously defined::
428
428
429 In [3]: ed foo
429 In [3]: ed foo
430 Editing... done. Executing edited code...
430 Editing... done. Executing edited code...
431
431
432 And if we call foo() again we get the modified version::
432 And if we call foo() again we get the modified version::
433
433
434 In [4]: foo()
434 In [4]: foo()
435 foo() has now been changed!
435 foo() has now been changed!
436
436
437 Here is an example of how to edit a code snippet successive
437 Here is an example of how to edit a code snippet successive
438 times. First we call the editor::
438 times. First we call the editor::
439
439
440 In [5]: ed
440 In [5]: ed
441 Editing... done. Executing edited code...
441 Editing... done. Executing edited code...
442 hello
442 hello
443 Out[5]: "print 'hello'\\n"
443 Out[5]: "print 'hello'\\n"
444
444
445 Now we call it again with the previous output (stored in _)::
445 Now we call it again with the previous output (stored in _)::
446
446
447 In [6]: ed _
447 In [6]: ed _
448 Editing... done. Executing edited code...
448 Editing... done. Executing edited code...
449 hello world
449 hello world
450 Out[6]: "print 'hello world'\\n"
450 Out[6]: "print 'hello world'\\n"
451
451
452 Now we call it with the output #8 (stored in _8, also as Out[8])::
452 Now we call it with the output #8 (stored in _8, also as Out[8])::
453
453
454 In [7]: ed _8
454 In [7]: ed _8
455 Editing... done. Executing edited code...
455 Editing... done. Executing edited code...
456 hello again
456 hello again
457 Out[7]: "print 'hello again'\\n"
457 Out[7]: "print 'hello again'\\n"
458
458
459
459
460 Changing the default editor hook:
460 Changing the default editor hook:
461
461
462 If you wish to write your own editor hook, you can put it in a
462 If you wish to write your own editor hook, you can put it in a
463 configuration file which you load at startup time. The default hook
463 configuration file which you load at startup time. The default hook
464 is defined in the IPython.core.hooks module, and you can use that as a
464 is defined in the IPython.core.hooks module, and you can use that as a
465 starting example for further modifications. That file also has
465 starting example for further modifications. That file also has
466 general instructions on how to set a new hook for use once you've
466 general instructions on how to set a new hook for use once you've
467 defined it."""
467 defined it."""
468 opts,args = self.parse_options(parameter_s,'prxn:')
468 opts,args = self.parse_options(parameter_s,'prxn:')
469
469
470 try:
470 try:
471 filename, lineno, is_temp = self._find_edit_target(self.shell,
471 filename, lineno, is_temp = self._find_edit_target(self.shell,
472 args, opts, last_call)
472 args, opts, last_call)
473 except MacroToEdit as e:
473 except MacroToEdit as e:
474 self._edit_macro(args, e.args[0])
474 self._edit_macro(args, e.args[0])
475 return
475 return
476
476
477 # do actual editing here
477 # do actual editing here
478 print 'Editing...',
478 print 'Editing...',
479 sys.stdout.flush()
479 sys.stdout.flush()
480 try:
480 try:
481 # Quote filenames that may have spaces in them
481 # Quote filenames that may have spaces in them
482 if ' ' in filename:
482 if ' ' in filename:
483 filename = "'%s'" % filename
483 filename = "'%s'" % filename
484 self.shell.hooks.editor(filename,lineno)
484 self.shell.hooks.editor(filename,lineno)
485 except TryNext:
485 except TryNext:
486 warn('Could not open editor')
486 warn('Could not open editor')
487 return
487 return
488
488
489 # XXX TODO: should this be generalized for all string vars?
489 # XXX TODO: should this be generalized for all string vars?
490 # For now, this is special-cased to blocks created by cpaste
490 # For now, this is special-cased to blocks created by cpaste
491 if args.strip() == 'pasted_block':
491 if args.strip() == 'pasted_block':
492 self.shell.user_ns['pasted_block'] = file_read(filename)
492 self.shell.user_ns['pasted_block'] = file_read(filename)
493
493
494 if 'x' in opts: # -x prevents actual execution
494 if 'x' in opts: # -x prevents actual execution
495 print
495 print
496 else:
496 else:
497 print 'done. Executing edited code...'
497 print 'done. Executing edited code...'
498 if 'r' in opts: # Untranslated IPython code
498 if 'r' in opts: # Untranslated IPython code
499 self.shell.run_cell(file_read(filename),
499 self.shell.run_cell(file_read(filename),
500 store_history=False)
500 store_history=False)
501 else:
501 else:
502 self.shell.safe_execfile(filename, self.shell.user_ns,
502 self.shell.safe_execfile(filename, self.shell.user_ns,
503 self.shell.user_ns)
503 self.shell.user_ns)
504
504
505 if is_temp:
505 if is_temp:
506 try:
506 try:
507 return open(filename).read()
507 return open(filename).read()
508 except IOError,msg:
508 except IOError,msg:
509 if msg.filename == filename:
509 if msg.filename == filename:
510 warn('File not found. Did you forget to save?')
510 warn('File not found. Did you forget to save?')
511 return
511 return
512 else:
512 else:
513 self.shell.showtraceback()
513 self.shell.showtraceback()
General Comments 0
You need to be logged in to leave comments. Login now