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